Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Issues with QScrollArea and custom widget
Forum Updated to NodeBB v4.3 + New Features

Issues with QScrollArea and custom widget

Scheduled Pinned Locked Moved Solved General and Desktop
qscrollarea
23 Posts 4 Posters 9.1k Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Joel BodenmannJ Offline
    Joel BodenmannJ Offline
    Joel Bodenmann
    wrote on last edited by Joel Bodenmann
    #1

    Hello folks,

    I have a custom widget named Display that inherits from QWidget. For the sake of argument, let's just assume that that widget just paints a QPixmap in its paintEvent() (because that's essentially what is happening).
    I took that custom widget and put it into a QScrollArea which I assigned as the central widget of my QMainWindow.

    My goal is to give the user the ability to zoom in and out of that custom widget (pixmap). For this I added a setScale(qreal scale) slot to my custom widget. It is essential that the aspect ratio of the custom widget doesn't change. To ensure this, my custom widget uses setFixedSize():

    Display::Display(int width, int height, QWidget* parent) : QWidget(parent), _width(width), _height(height), _scale(1.0)
    {
       ...
       // Configuration
       setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
       setFixedSize(width, height);
       ...
    }
    
    void Display::setScale(qreal scale)
    {
        setFixedSize(scale*_width, scale*_height);
    
        _scale = scale;
    }
    
    QSize Display::sizeHint() const
    {
        return QSize(_scale*_width, _scale*_height);
    }
    

    However, the QScrollArea still changes the aspect ratio of my widget if I zoom in so far that the scroll bars appear. Furthermore, even then the panning doesn't actually work.
    I made a video that demonstrates this problem: https://www.screencast.com/t/LYYHT8QhFZ

    What am I doing wrong? I'd appreciate any help on this.

    Industrial process automation software: https://simulton.com
    Embedded Graphics & GUI library: https://ugfx.io

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Charlie_Hdz
      wrote on last edited by
      #2

      So you want to keep the relation of the width and height of the pixmap?

      Kind Regards,

      Enrique Hernandez

      Kind Regards,
      Enrique Hernandez
      gearstech.com.mx
      chernandez@gearstech.com.mx

      1 Reply Last reply
      0
      • Joel BodenmannJ Offline
        Joel BodenmannJ Offline
        Joel Bodenmann
        wrote on last edited by Joel Bodenmann
        #3

        Yes, but in this case the size of the Display (QWidget subclass) must keep the aspect ratio as well. This is not just about modifying Display::paintEvent() to draw the pixmap with the correct aspect ratio.

        The Display class represents a virtual display of a given size in pixels.

        Industrial process automation software: https://simulton.com
        Embedded Graphics & GUI library: https://ugfx.io

        1 Reply Last reply
        0
        • kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          Hey, long time no see!

          How do you build the scroll area, do you have a layout there? Mind showing the code/designer form (screenshot's fine)?

          It seems to me your initial values for width and height are wrong for some reason. You could try painting the widget background red (or a bright color) so you can get a glimpse of what it covers (beside the image itself).

          PS.
          The size hint doesn't do much here, as you've set all things to be fixed size, there's nothing to hint really. ;)

          Read and abide by the Qt Code of Conduct

          Joel BodenmannJ 1 Reply Last reply
          0
          • kshegunovK kshegunov

            Hey, long time no see!

            How do you build the scroll area, do you have a layout there? Mind showing the code/designer form (screenshot's fine)?

            It seems to me your initial values for width and height are wrong for some reason. You could try painting the widget background red (or a bright color) so you can get a glimpse of what it covers (beside the image itself).

            PS.
            The size hint doesn't do much here, as you've set all things to be fixed size, there's nothing to hint really. ;)

            Joel BodenmannJ Offline
            Joel BodenmannJ Offline
            Joel Bodenmann
            wrote on last edited by
            #5

            Hey man! Glad to see you alive :)

            How do you build the scroll area, do you have a layout there? Mind showing the code/designer form (screenshot's fine)?

            Sure, I have nothing to hide. But then again, there's is nothing really to show.
            Here's how I create the QScrollArea and add it as the central widget of the QMainWindow:

                // Central scroll area
                _centralScrollArea = new QScrollArea(this);
                _centralScrollArea->setFrameShape(QFrame::NoFrame);
                _centralScrollArea->setAlignment(Qt::AlignCenter);
                _centralScrollArea->setWidgetResizable(false);
            
                // Central widget
                QVBoxLayout* centralWidgetLayout = new QVBoxLayout;
                centralWidgetLayout->addWidget(_toolbar);
                centralWidgetLayout->addWidget(_centralScrollArea);
                QWidget* centralWidget = new QWidget(this);
                centralWidget->setLayout(centralWidgetLayout);
                setCentralWidget(centralWidget);
            

            _toolBar is just a regular QToolBar. I add it in that layout instead of using QMainWindow::addToolbar() because I want the toolbar to be between the QDockWidgets that I have left and right of the central widget.

            It seems to me your initial values for width and height are wrong for some reason. You could try painting the widget background red (or a bright color) so you can get a glimpse of what it covers (beside the image itself).

            What makes you think that the initial values for width and height of my custom widget are wrong? I checked them and they are fine. The widget is exactly the size I expect it to be. There's really no issue with my custom widget as long as I don't zoom into the QScrollArea deep enough to make it screw up the aspect ration (and make it fail the panning).

            PS. The size hint doesn't do much here, as you've set all things to be fixed size, there's nothing to hint really. ;)

            I was getting desperate ;)

            If it helps, here's the source of my custom widget (the one that I put into the QScrollArea): ugfxdisplay.cpp
            It's a QWidget wrapper around the GDisplay provided by the µGFX library. It's like a virtual display inside of a QWidget. All it does is proxy stuff around.

            Industrial process automation software: https://simulton.com
            Embedded Graphics & GUI library: https://ugfx.io

            kshegunovK 1 Reply Last reply
            0
            • Joel BodenmannJ Joel Bodenmann

              Hey man! Glad to see you alive :)

              How do you build the scroll area, do you have a layout there? Mind showing the code/designer form (screenshot's fine)?

              Sure, I have nothing to hide. But then again, there's is nothing really to show.
              Here's how I create the QScrollArea and add it as the central widget of the QMainWindow:

                  // Central scroll area
                  _centralScrollArea = new QScrollArea(this);
                  _centralScrollArea->setFrameShape(QFrame::NoFrame);
                  _centralScrollArea->setAlignment(Qt::AlignCenter);
                  _centralScrollArea->setWidgetResizable(false);
              
                  // Central widget
                  QVBoxLayout* centralWidgetLayout = new QVBoxLayout;
                  centralWidgetLayout->addWidget(_toolbar);
                  centralWidgetLayout->addWidget(_centralScrollArea);
                  QWidget* centralWidget = new QWidget(this);
                  centralWidget->setLayout(centralWidgetLayout);
                  setCentralWidget(centralWidget);
              

              _toolBar is just a regular QToolBar. I add it in that layout instead of using QMainWindow::addToolbar() because I want the toolbar to be between the QDockWidgets that I have left and right of the central widget.

              It seems to me your initial values for width and height are wrong for some reason. You could try painting the widget background red (or a bright color) so you can get a glimpse of what it covers (beside the image itself).

              What makes you think that the initial values for width and height of my custom widget are wrong? I checked them and they are fine. The widget is exactly the size I expect it to be. There's really no issue with my custom widget as long as I don't zoom into the QScrollArea deep enough to make it screw up the aspect ration (and make it fail the panning).

              PS. The size hint doesn't do much here, as you've set all things to be fixed size, there's nothing to hint really. ;)

              I was getting desperate ;)

              If it helps, here's the source of my custom widget (the one that I put into the QScrollArea): ugfxdisplay.cpp
              It's a QWidget wrapper around the GDisplay provided by the µGFX library. It's like a virtual display inside of a QWidget. All it does is proxy stuff around.

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #6

              @Joel-Bodenmann said in Issues with QScrollArea and custom widget:

              Hey man! Glad to see you alive :)

              Surprising, right? ;)

              What makes you think that the initial values for width and height of my custom widget are wrong?

              We old people often get confused. I noticed something strange about the scrollbars but perhaps that's nothing.

              QImage img((const uchar*)pixmapSurface, width(), height(), width()*sizeof(color_t), QImage::Format_RGB32);
              painter.drawImage(event->rect(), img, img.rect());
              

              Can you check how width() relates to _width and the same for the height here? I'm pretty sure you'd find them to differ.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • Joel BodenmannJ Offline
                Joel BodenmannJ Offline
                Joel Bodenmann
                wrote on last edited by
                #7

                Surprising, right? ;)

                Not really, given all the "healthy" food you eat ;)

                Can you check how width() relates to _width and the same for the height here? I'm pretty sure you'd find them to differ.
                Well... how can I say this but:

                int UGfxDisplay::width() const
                {
                    return _width;
                }
                

                I don't see how that could possibly go wrong. Unless... is this a shadowing problem?

                Industrial process automation software: https://simulton.com
                Embedded Graphics & GUI library: https://ugfx.io

                kshegunovK 1 Reply Last reply
                0
                • Joel BodenmannJ Joel Bodenmann

                  Surprising, right? ;)

                  Not really, given all the "healthy" food you eat ;)

                  Can you check how width() relates to _width and the same for the height here? I'm pretty sure you'd find them to differ.
                  Well... how can I say this but:

                  int UGfxDisplay::width() const
                  {
                      return _width;
                  }
                  

                  I don't see how that could possibly go wrong. Unless... is this a shadowing problem?

                  kshegunovK Offline
                  kshegunovK Offline
                  kshegunov
                  Moderators
                  wrote on last edited by kshegunov
                  #8

                  @Joel-Bodenmann said in Issues with QScrollArea and custom widget:

                  I don't see how that could possibly go wrong. Unless... is this a shadowing problem?

                  Possibly, yes, try to rename those two methods to something. To be honest I don't really know what width() should return for a widget inside a scroll area, but my spidy sense is tingling. Notice that you get the scrolls when one of the dimensions reaches the scroll area border. That makes me think it's a "bad drawing" on your part, some mismatch of image/widget rects.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  0
                  • Joel BodenmannJ Offline
                    Joel BodenmannJ Offline
                    Joel Bodenmann
                    wrote on last edited by
                    #9

                    I just checked (using qDebug() inside UGfxDisplay::paintEvent()) and they (UGfxDisplay::_width() and UGfxDisplay::width()) are always the same value (and they don't change when zooming).
                    Keep in mind that UGfxDisplay::width() returns the width of my virtual display which is not supposed to change even if the person zooms in. This is not like QWidget::width() which would return _width * _scale (which it does as I always call QWidget::setFixedSize(_scale*_width, _scale*_height).

                    I assume that QScrollArea calls QWidget::width() and not UGfxDisplay::width() as it only has the pointer to the QWidget anyway.

                    Renaming my width() and height() methods would be quite an effort as they are used on many places. Is the QtCreator refactoring algorithm up to the task? ;)

                    Industrial process automation software: https://simulton.com
                    Embedded Graphics & GUI library: https://ugfx.io

                    kshegunovK 1 Reply Last reply
                    0
                    • Joel BodenmannJ Joel Bodenmann

                      I just checked (using qDebug() inside UGfxDisplay::paintEvent()) and they (UGfxDisplay::_width() and UGfxDisplay::width()) are always the same value (and they don't change when zooming).
                      Keep in mind that UGfxDisplay::width() returns the width of my virtual display which is not supposed to change even if the person zooms in. This is not like QWidget::width() which would return _width * _scale (which it does as I always call QWidget::setFixedSize(_scale*_width, _scale*_height).

                      I assume that QScrollArea calls QWidget::width() and not UGfxDisplay::width() as it only has the pointer to the QWidget anyway.

                      Renaming my width() and height() methods would be quite an effort as they are used on many places. Is the QtCreator refactoring algorithm up to the task? ;)

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      No idea, my code is usually so bad it doesn't need refactoring but plain rewriting. ;)

                      Anyway, forget that for a moment, can you try something like this:

                      painter.drawImage(event->rect(), img, img.rect().intersected(event->rect()));
                      

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      0
                      • Joel BodenmannJ Offline
                        Joel BodenmannJ Offline
                        Joel Bodenmann
                        wrote on last edited by
                        #11

                        @kshegunov said in Issues with QScrollArea and custom widget:

                        No idea, my code is usually so bad it doesn't need refactoring but plain rewriting. ;)

                        Still waiting on my QAbstractModel merging thingy ;)

                        Anyway, forget that for a moment, can you try something like this:

                        Here you go: https://www.screencast.com/t/nNbHckWi

                        Industrial process automation software: https://simulton.com
                        Embedded Graphics & GUI library: https://ugfx.io

                        kshegunovK 1 Reply Last reply
                        0
                        • Joel BodenmannJ Joel Bodenmann

                          @kshegunov said in Issues with QScrollArea and custom widget:

                          No idea, my code is usually so bad it doesn't need refactoring but plain rewriting. ;)

                          Still waiting on my QAbstractModel merging thingy ;)

                          Anyway, forget that for a moment, can you try something like this:

                          Here you go: https://www.screencast.com/t/nNbHckWi

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #12

                          @Joel-Bodenmann said in Issues with QScrollArea and custom widget:

                          Still waiting on my QAbstractModel merging thingy ;)

                          I know, I know.

                          Here you go: https://www.screencast.com/t/nNbHckWi

                          Well, something moved at least. Can you get the paint rects you get when zoomin in/out and when you scroll up/down/left/right along with the image rects and dump them all into a file?

                          Read and abide by the Qt Code of Conduct

                          Joel BodenmannJ 1 Reply Last reply
                          0
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            Hi,

                            Might be a silly question but how are you handling UGfxDisplay ?

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            0
                            • Joel BodenmannJ Offline
                              Joel BodenmannJ Offline
                              Joel Bodenmann
                              wrote on last edited by
                              #14

                              @kshegunov said in Issues with QScrollArea and custom widget:

                              Well, something moved at least. Can you get the paint rects you get when zoomin in/out and when you scroll up/down/left/right along with the image rects and dump them all into a file?

                              Sure, I'll get that done.

                              @SGaist said in Issues with QScrollArea and custom widget:

                              Might be a silly question but how are you handling UGfxDisplay ?

                              I'm sorry, I don't understand what handling means in this context. Can you be more specific?

                              Industrial process automation software: https://simulton.com
                              Embedded Graphics & GUI library: https://ugfx.io

                              1 Reply Last reply
                              0
                              • SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                Are you calling something like _centralScrollArea->setWidget(_myGDisplay); ?

                                Then, are you sure that you should handle the scaling in GDisplay ?

                                When zooming, what about having something like _myGDisplay->resize(_scale * _sourceSize); So you only handle painting in that widget.

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                1 Reply Last reply
                                0
                                • kshegunovK kshegunov

                                  @Joel-Bodenmann said in Issues with QScrollArea and custom widget:

                                  Still waiting on my QAbstractModel merging thingy ;)

                                  I know, I know.

                                  Here you go: https://www.screencast.com/t/nNbHckWi

                                  Well, something moved at least. Can you get the paint rects you get when zoomin in/out and when you scroll up/down/left/right along with the image rects and dump them all into a file?

                                  Joel BodenmannJ Offline
                                  Joel BodenmannJ Offline
                                  Joel Bodenmann
                                  wrote on last edited by
                                  #16

                                  @kshegunov said in Issues with QScrollArea and custom widget:

                                  Well, something moved at least. Can you get the paint rects you get when zoomin in/out and when you scroll up/down/left/right along with the image rects and dump them all into a file?

                                  Here you go: http://paste.ugfx.io/show/a5113bcc08

                                  @SGaist said in Issues with QScrollArea and custom widget:

                                  Are you calling something like _centralScrollArea->setWidget(_myGDisplay); ?

                                  Yep, that's what I am doing.

                                  @SGaist said in Issues with QScrollArea and custom widget:

                                  When zooming, what about having something like _myGDisplay->resize(_scale * _sourceSize); So you only handle painting in that widget.

                                  In my opinion that won't work as it will not scale up the contents inside of my UGfxDisplay. Keep in mind that the QPixmap I draw in my UGfxDisplay::paintEvent() is the content of a virtual display. That virtual display has a given size (width and height) in pixels. When zooming in I need to scale up everything. I don't display more of the widget, I just display the same content bigger.

                                  Industrial process automation software: https://simulton.com
                                  Embedded Graphics & GUI library: https://ugfx.io

                                  kshegunovK 1 Reply Last reply
                                  0
                                  • Joel BodenmannJ Joel Bodenmann

                                    @kshegunov said in Issues with QScrollArea and custom widget:

                                    Well, something moved at least. Can you get the paint rects you get when zoomin in/out and when you scroll up/down/left/right along with the image rects and dump them all into a file?

                                    Here you go: http://paste.ugfx.io/show/a5113bcc08

                                    @SGaist said in Issues with QScrollArea and custom widget:

                                    Are you calling something like _centralScrollArea->setWidget(_myGDisplay); ?

                                    Yep, that's what I am doing.

                                    @SGaist said in Issues with QScrollArea and custom widget:

                                    When zooming, what about having something like _myGDisplay->resize(_scale * _sourceSize); So you only handle painting in that widget.

                                    In my opinion that won't work as it will not scale up the contents inside of my UGfxDisplay. Keep in mind that the QPixmap I draw in my UGfxDisplay::paintEvent() is the content of a virtual display. That virtual display has a given size (width and height) in pixels. When zooming in I need to scale up everything. I don't display more of the widget, I just display the same content bigger.

                                    kshegunovK Offline
                                    kshegunovK Offline
                                    kshegunov
                                    Moderators
                                    wrote on last edited by
                                    #17

                                    Have you noticed your image doesn't grow (or shrink)?

                                    Read and abide by the Qt Code of Conduct

                                    1 Reply Last reply
                                    0
                                    • Joel BodenmannJ Offline
                                      Joel BodenmannJ Offline
                                      Joel Bodenmann
                                      wrote on last edited by
                                      #18

                                      The image is not supposed to grow. The image represents the contents of the virtual display. It will always have the same amount of pixels no matter how much I zoom into the UGfxDisplay widget. My virtual display does not grow by zooming into it :p

                                      Industrial process automation software: https://simulton.com
                                      Embedded Graphics & GUI library: https://ugfx.io

                                      kshegunovK 1 Reply Last reply
                                      0
                                      • Joel BodenmannJ Joel Bodenmann

                                        The image is not supposed to grow. The image represents the contents of the virtual display. It will always have the same amount of pixels no matter how much I zoom into the UGfxDisplay widget. My virtual display does not grow by zooming into it :p

                                        kshegunovK Offline
                                        kshegunovK Offline
                                        kshegunov
                                        Moderators
                                        wrote on last edited by kshegunov
                                        #19

                                        But why are you redrawing reinitializing it at each paint event then? It got me confused, now I believe I know what you want. Should be something like this (I *think*):

                                        painter.drawImage(event->rect(), img, event->rect() / _scale);
                                        

                                        PS. Or not. I need to think.
                                        PS. After thinking:

                                        QRect paintRect = event->rect();
                                        QRect sourceRect(paintRect.topLeft() / _scale, paintRect.size() / _scale);
                                        painter.drawImage(paintRect, img, sourceRect);
                                        

                                        Read and abide by the Qt Code of Conduct

                                        1 Reply Last reply
                                        2
                                        • Joel BodenmannJ Offline
                                          Joel BodenmannJ Offline
                                          Joel Bodenmann
                                          wrote on last edited by Joel Bodenmann
                                          #20

                                          Wooo, I love you \o/ (still, not again, don't worry honey)

                                          This is with your "After thinking" code: https://www.screencast.com/t/cEAa2z4Zd

                                          In retrospect this seems somewhat obvious...

                                          Industrial process automation software: https://simulton.com
                                          Embedded Graphics & GUI library: https://ugfx.io

                                          kshegunovK 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved