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. QScrollArea sizing issue
Forum Updated to NodeBB v4.3 + New Features

QScrollArea sizing issue

Scheduled Pinned Locked Moved Solved General and Desktop
15 Posts 3 Posters 8.2k Views 3 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.
  • JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #1

    I'm struggling with a QScrollArea sizing issue, and would appreciate a hint. I'm a newb, I'm pretty tired working on this. So please excuse me.

    I started from existing code in a large program with a QDialog containing a QVBoxLayout with many controls. In outline:

    # self == QDialog
    self.vertLayout = QVBoxLayout(self)
    ...
    

    This gave me a dialog as wide/high as needed for content, limited to dialog size, but had so much vertical content it was off the bottom.

    All I need is a vertical scroller inside dialog around content to make it reasonable. After a bit of a struggle (and some help to finally find a simple example at https://stackoverflow.com/a/28826793/489865), I have moved to:

    # self == QDialog
    scrollArea = QScrollArea(self)
    scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
    scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
    # scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
    scrollArea.setWidgetResizable(True)
    scrollArea.setFixedHeight(400)
    
    widget = QWidget()
    scrollArea.setWidget(widget)
    
    self.vertLayout = QVBoxLayout()
    widget.setLayout(self.vertLayout)
    ...
    

    This is great, in that vertically I get the scrollbar I need. However, the bit I don't get is that I also now have the horizontal content's width limited, such that it needs a horizontal scrollbar and/or it gets truncated horizontally. In short, horizontally it nowhere near fills the width of the dialog any longer.

    0_1507909934462_Screenshot from 2017-10-13 16-50-44.png
    I don't understand to what or why there is a horizontal limit being applied here? I've played a bit with code & debugger but no wiser.

    I'd like the content to take up as much room horizontally as it used to, but limit the verticality to require scrolling. Please.

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by mrjj
      #2

      @JNBarchan said in QScrollArea sizing issue:

      Hi
      first of all
      this reads funny

      self.vertLayout = QVBoxLayout()
      widget.setLayout(self.vertLayout)

      ahh no. just pyt confusing me . its the same as
      VBoxLayout *layout = new QVBoxLayout();
      if layout is a class member.
      like you give the dialogs layout to the widget ?
      Maybe just syntax. They cannot share a layout.

      anyway, can you try to insert the scrollarea into the dialogs layout ?

      self.layout().addWidget( ScrollArea);

      The code you link to suffer the same

      alt text

      The dialog have no layout of its own and hence it wont use all of dialogs size.

      I think you have same issue as
      self.vertLayout = QVBoxLayout()
      widget.setLayout(self.vertLayout)

      creates the layout and give to widget ?

      so seems the SELF dialog have no layout and hence wont make
      scroll area take up all space.

      JonBJ 1 Reply Last reply
      2
      • mrjjM mrjj

        @JNBarchan said in QScrollArea sizing issue:

        Hi
        first of all
        this reads funny

        self.vertLayout = QVBoxLayout()
        widget.setLayout(self.vertLayout)

        ahh no. just pyt confusing me . its the same as
        VBoxLayout *layout = new QVBoxLayout();
        if layout is a class member.
        like you give the dialogs layout to the widget ?
        Maybe just syntax. They cannot share a layout.

        anyway, can you try to insert the scrollarea into the dialogs layout ?

        self.layout().addWidget( ScrollArea);

        The code you link to suffer the same

        alt text

        The dialog have no layout of its own and hence it wont use all of dialogs size.

        I think you have same issue as
        self.vertLayout = QVBoxLayout()
        widget.setLayout(self.vertLayout)

        creates the layout and give to widget ?

        so seems the SELF dialog have no layout and hence wont make
        scroll area take up all space.

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @mrjj
        I will try your suggestion as soon as I am able.

        However, although I confess I could be misunderstanding, the reason I didn't think that was necessary is because of http://doc.qt.io/qt-5/qwidget.html#setLayout:

        void QWidget::setLayout(QLayout *layout)
        An alternative to calling this function is to pass this widget to the layout's constructor.

        So "to insert the scrollarea into the dialogs layout " you want:
        self.layout().addWidget(scrollArea);
        and I already have:
        scrollArea = QScrollArea(self)
        (not just QScrollArea() constructor) which I understand to do same thing as calling setLayout(scrollArea) explicitly, no?

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

          Hi,

          No, not at all. With scrollArea = QScrollArea(self) you are just giving it a parent and when you call show on it, it will be shown in the parent viewport.

          With setLayout(scrollArea), that's just wrong. You can't set a widget as layout.

          So neither are doing what you want.

          In the constructor of your dialog you should have something like:

          layout = QVBoxLayout()
          layout->addWidget(scrollArea)
          self.setLayout(layout)
          

          or the short version:

          layout = QVBoxLayout(self) # Create a layout and apply it to it's parent
          layout->addWidget(scrollArea)
          

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

          JonBJ 1 Reply Last reply
          3
          • SGaistS SGaist

            Hi,

            No, not at all. With scrollArea = QScrollArea(self) you are just giving it a parent and when you call show on it, it will be shown in the parent viewport.

            With setLayout(scrollArea), that's just wrong. You can't set a widget as layout.

            So neither are doing what you want.

            In the constructor of your dialog you should have something like:

            layout = QVBoxLayout()
            layout->addWidget(scrollArea)
            self.setLayout(layout)
            

            or the short version:

            layout = QVBoxLayout(self) # Create a layout and apply it to it's parent
            layout->addWidget(scrollArea)
            
            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @SGaist
            Thanks for this, when I get back to code I will review in this light.

            Does that indeed mean that the example I copied from, https://stackoverflow.com/a/28826793/489865, is not right, as @mrjj was suggesting? That posts says, and I (thought I) followed the code:

            •on the bottom is parent widget (for example QDialog)
            •on top of this is scrollable area (QScrollArea) of fixed size

            i.e. scrollarea straight on dialog, you are putting it on layout, he does not do that? I am getting really confused with the layers of widgets/layouts/scrollareas... :(

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

              No, the content of the widget is described correctly on that post.

              The two points of interest:

              • on the bottom is parent widget (for example QDialog)
              • on top of this is scrollable area (QScrollArea) of fixed size

              You see ? No layouts involved there. The fact that it's passing a parent to the QScrollArea makes it appear within the dialog.

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

              JonBJ 1 Reply Last reply
              0
              • SGaistS SGaist

                No, the content of the widget is described correctly on that post.

                The two points of interest:

                • on the bottom is parent widget (for example QDialog)
                • on top of this is scrollable area (QScrollArea) of fixed size

                You see ? No layouts involved there. The fact that it's passing a parent to the QScrollArea makes it appear within the dialog.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @SGaist
                Thanks, but I thought I was to do the same as him, yet in mine you're telling me I need a QVBoxLayout that he does not need.....

                I started with a dialog with a vboxlayout and some content. My content overflows the dialog vertically. I want to have a vertical scrollbar against the side of the dialog for its content. That's all I want to add to the original code. I'm finding this mega-complex.... :(

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

                  What the examples shows is how a QScrollArea work not how to make it fit in a widget.

                  From your description you want your scroll area to fill your widget so that you don't have to resize it, hence you need to put the area in a layout applied to said widget.

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

                  JonBJ 1 Reply Last reply
                  1
                  • SGaistS SGaist

                    What the examples shows is how a QScrollArea work not how to make it fit in a widget.

                    From your description you want your scroll area to fill your widget so that you don't have to resize it, hence you need to put the area in a layout applied to said widget.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #9

                    @SGaist
                    OK, thanks, I'll have a play.

                    All I need to understand is the hierarchy I need. If I started with
                    dialog -> vboxlayout1 -> content
                    I will now need
                    dialog -> vboxlayout2 -> scrollarea ( -> widget ?) -> vboxlayout1 -> content
                    Is that right? I'll need a separate vboxlayout from the one I started from, I don't somehow apply the scrollarea to the original vboxlayout?

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

                      To make things clearer:

                      widget -> vboxlayout1 -> content <- future content of the QScrollArea

                      dialog -> vboxlayout2 -> scrollarea <- QScrollArea fitting the "main widget"

                      scrollarea -> widget <- finally your widget in the QScrollArea

                      See QScrollArea::setWidget

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

                      JonBJ 1 Reply Last reply
                      1
                      • SGaistS SGaist

                        To make things clearer:

                        widget -> vboxlayout1 -> content <- future content of the QScrollArea

                        dialog -> vboxlayout2 -> scrollarea <- QScrollArea fitting the "main widget"

                        scrollarea -> widget <- finally your widget in the QScrollArea

                        See QScrollArea::setWidget

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #11

                        @SGaist
                        OK, thanks a lot, at least I know what I'm trying to achieve now! :) Will try and report back.

                        JonBJ 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @SGaist
                          OK, thanks a lot, at least I know what I'm trying to achieve now! :) Will try and report back.

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by JonB
                          #12

                          @SGaist
                          OK, armed with the understanding of what the actual hierarchy should be, I have now modified to outline:

                          # self == QDialog
                          self.dialogScrollPanel = QVBoxLayout()
                          self.setLayout(self.dialogScrollPanel)
                          
                          scrollArea = QScrollArea(self)
                          scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
                          scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
                          scrollArea.setWidgetResizable(True)
                          self.dialogScrollPanel.addWidget(scrollArea)
                          
                          widget = QWidget()
                          scrollArea.setWidget(widget)
                          
                          self.vertLayout = QVBoxLayout()
                          widget.setLayout(self.vertLayout)
                          ...
                          

                          And sure enough my dialog now looks like:
                          alt text
                          which is just what I was aiming for!

                          The one bit I'm left hazy on is when you do or do not need to specify an owner/parent for a layout or widget. My code includes:

                          self.dialogScrollPanel = QVBoxLayout()
                          self.setLayout(self.dialogScrollPanel)
                          
                          widget = QWidget()
                          scrollArea.setWidget(widget)
                          
                          self.vertLayout = QVBoxLayout()
                          widget.setLayout(self.vertLayout)
                          

                          In each of these cases the constructor could equally be QVBoxLayout(self) or QWidget(self) and I see the same behaviour. In the code I've inherited it seems sometimes it passes an argument to these and sometimes not. When do I need or not need to pass a widget parent/owner argument when creating a widget or layout?

                          mrjjM 1 Reply Last reply
                          0
                          • JonBJ JonB

                            @SGaist
                            OK, armed with the understanding of what the actual hierarchy should be, I have now modified to outline:

                            # self == QDialog
                            self.dialogScrollPanel = QVBoxLayout()
                            self.setLayout(self.dialogScrollPanel)
                            
                            scrollArea = QScrollArea(self)
                            scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
                            scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
                            scrollArea.setWidgetResizable(True)
                            self.dialogScrollPanel.addWidget(scrollArea)
                            
                            widget = QWidget()
                            scrollArea.setWidget(widget)
                            
                            self.vertLayout = QVBoxLayout()
                            widget.setLayout(self.vertLayout)
                            ...
                            

                            And sure enough my dialog now looks like:
                            alt text
                            which is just what I was aiming for!

                            The one bit I'm left hazy on is when you do or do not need to specify an owner/parent for a layout or widget. My code includes:

                            self.dialogScrollPanel = QVBoxLayout()
                            self.setLayout(self.dialogScrollPanel)
                            
                            widget = QWidget()
                            scrollArea.setWidget(widget)
                            
                            self.vertLayout = QVBoxLayout()
                            widget.setLayout(self.vertLayout)
                            

                            In each of these cases the constructor could equally be QVBoxLayout(self) or QWidget(self) and I see the same behaviour. In the code I've inherited it seems sometimes it passes an argument to these and sometimes not. When do I need or not need to pass a widget parent/owner argument when creating a widget or layout?

                            mrjjM Offline
                            mrjjM Offline
                            mrjj
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            @JNBarchan

                            Any widget that is not given a parent will become a window.
                            So for any widget on a from, you will want to give it a parent.
                            However, inserting them into other widgets set the parent.

                            For Layouts, its its easier just to assign them to a widget and in that
                            way give a parent.

                            So in most cases you will just want to give a parent when constructed as
                            to make sure they are deleted.

                            JonBJ 1 Reply Last reply
                            2
                            • mrjjM mrjj

                              @JNBarchan

                              Any widget that is not given a parent will become a window.
                              So for any widget on a from, you will want to give it a parent.
                              However, inserting them into other widgets set the parent.

                              For Layouts, its its easier just to assign them to a widget and in that
                              way give a parent.

                              So in most cases you will just want to give a parent when constructed as
                              to make sure they are deleted.

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by
                              #14

                              @mrjj
                              Thanks. I suspect the key is:

                              However, inserting them into other widgets set the parent.

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

                                I usually follow these rules:

                                • When I create layout that should be the "main" layout of a widget, I pass that widget as parent
                                  Note that's just an habit, if you prefer the setLayout method then go for it, just be consistent all over your code base.
                                • All widgets that are put inside a layout will be re-parented appropriately so I don't pass a parent to them.
                                • Unless I'm going to manipulate the layout later on I don't make it a member of the class

                                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
                                1

                                • Login

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