QLabel showing an image inside a QScrollArea
Asked Answered
E

2

7

I've successfully implemented a Image Viewer (for DICOM) in Qt. I can see the image and I can zoom in and out correctly.

Now, I want to see scroll bars if the image is too big to show when I zoom in.

I've used the UI. I placed a QScrollArea. Inside, the QLabel. The verticalScrollBarPolicy is ScrollBarAsNeeded. The horizontalScrollBarPolicy is ScrollBarAsNeeded.

The problem is: it doesn't work. I zoom in, but no scrollbar appears.

Second try: using a layout inside the QScrollArea.

So now there's a QWidget between the QScrollArea and the QLabel: a horizontal layout. Opened the same image, now I can see a vertical scroll bar on the right. The image is streched from left to right. When I zoom the image gets its correct proportion.

BUT... I zoom out and the scroll bar is the same, even if I can see the whole image. The horizontal scroll bar never appears.

Resizing the QLabel doesn't seem to affect. But if I resize the QScrollArea (resizing the main window) the horizontal scroll bar appears.

I've been checking some numbers:

In the QScrollArea

  • Its size changes: below 599 width (why this number? I can't see it anywhere) the horizontal bar appears.
  • sizeHint() always returns the same values: 33x41

In the QLabel

  • The dimensions change, but that doesn't affect.
  • sizeHint() always returns the same values: 560x1558

Here is the code in XML from the UI designer:

<widget class="QWidget" name="centralWidget">
   <property name="autoFillBackground">
    <bool>false</bool>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <property name="margin">
     <number>0</number>
    </property>
    <item>
     <widget class="QScrollArea" name="scrollArea">
      <property name="widgetResizable">
       <bool>true</bool>
      </property>
      <property name="alignment">
       <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
      </property>
      <widget class="QWidget" name="scrollAreaWidgetContents">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>637</width>
         <height>649</height>
        </rect>
       </property>
       <layout class="QHBoxLayout" name="horizontalLayout_2">
        <item>
         <widget class="QLabel" name="miImagen">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
            <horstretch>0</horstretch>
            <verstretch>0</verstretch>
           </sizepolicy>
          </property>
          <property name="autoFillBackground">
           <bool>true</bool>
          </property>
          <property name="scaledContents">
           <bool>true</bool>
          </property>
          <property name="alignment">
           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>

What am I missing? Thank you.

Esoterica answered 11/6, 2012 at 14:2 Comment(4)
What do you mean 'zoom in'? The scroll bars will only appear if the QLabel becomes larger than the QScrollArea.Rottenstone
Yes, when I zoom in, the QLabel becomes larger because I get more detail in that image. The image grows.Esoterica
Please post the code where you create and set the properties for the widgets.Rottenstone
XML code added. I guess it's something about QScrollArea not noticing the QLabel is changing its size, so it only responds when I change its dimensions, not the QLabel's dimensions.Esoterica
S
4

I know this is an old post - but in case you or anyone is still having a problem, it might help to set QScrollArea::widgetResizable to false.

At least, when I tried a similar thing, my vertical scrollbar was always disabled (even though I set the size of the scrollable widget to have a height larger than the viewport) until I set this to false.

When it's true, I think it updates the size of the scrollable widget, thus the scrollbars should not be needed. This allows you to do what it does in the example I guess, and implement a stretch-to-fit function. (actually what I'm trying to do is fit to width, with just a vertical scroll bar)

Slaver answered 25/8, 2012 at 15:20 Comment(0)
D
2

Have you tried following Qt's scroll area example? If you're using a QLabel to display your image, then the use of QScrollArea is pretty much the standard way of achieving what you want. You use it like so (from the example):

 imageLabel = new QLabel;
 imageLabel->setBackgroundRole(QPalette::Base);
 imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
 imageLabel->setScaledContents(true);

 scrollArea = new QScrollArea;
 scrollArea->setBackgroundRole(QPalette::Dark);
 scrollArea->setWidget(imageLabel);
 setCentralWidget(scrollArea);

Then zooming is handled like so:

 void ImageViewer::zoomIn() { 
    scaleImage(1.25);
 }

 void ImageViewer::zoomOut() {
     scaleImage(0.8);
 }

 void ImageViewer::scaleImage(double factor)
 {
     Q_ASSERT(imageLabel->pixmap());
     scaleFactor *= factor;
     imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());

     adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
     adjustScrollBar(scrollArea->verticalScrollBar(), factor);

     zoomInAct->setEnabled(scaleFactor < 3.0);
     zoomOutAct->setEnabled(scaleFactor > 0.333);
 }

 void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor) {
     scrollBar->setValue(int(factor * scrollBar->value()
                         + ((factor - 1) * scrollBar->pageStep()/2)));
 }

You can, of course, get a better idea of what's going on by looking at the example, but that's the gist of it. I think perhaps the adjustScrollBar() function might be the most helpful thing for you.

Your last comment on the original post is correct, the QScrollArea doesn't magically notice the change in size of its contents. Look at how the example uses adjustScrollBar() to compensate for this fact.

Dunne answered 11/6, 2012 at 21:58 Comment(3)
In fact, this Qt example is the one I'm using to do my application. I have those functions implemented. The bars don't appear. The only difference is that, in XML version, I you can't implement scrollArea->setWidget(imageLabel) and setCentralWidget(scrollArea) sentences. I guess the first one is like dragging the imageLabel inside the scrollarea. I tried the second one, and the application crushes.Esoterica
Well, I detected the error, but I don't know why is that: scrollArea->horizontalScrollBar()->setValue() doesn't do anything. The value passed to setValue is negative or positive, always different, but the value of both scrollbars is still 0. Always! :(Esoterica
In similar code to this example I found the scrollbars only appeared if I set minimum sizes for the imageLabel - which was suggested here: forum.qt.io/topic/31189/qlabel-won-t-expand-when-in-qscrollarea/…Gawlas

© 2022 - 2024 — McMap. All rights reserved.