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. Layout is changing when using QScrollArea in PyQt5
Forum Updated to NodeBB v4.3 + New Features

Layout is changing when using QScrollArea in PyQt5

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 2 Posters 1.2k Views 2 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.
  • D Offline
    D Offline
    deleted412
    wrote on 6 Jan 2021, 16:04 last edited by
    #1

    Hello. I am having a problem when using QScrollArea in PyQt5.

    I have attached two widgets to a QStackedWidget in a QScrollArea. I am adding labels to the layouts of the two individual widgets that I am attaching to this QStackedWidget.

    However, when I switch back and forth between the two widgets in my Scroll Area, the layout changes for both widgets. If you continue to press back and forth, the labels continue to "slide" down the second widget.

    I would like the layouts to stay the exact same for each individual layout, for each individual widget in the Scroll Area, and not be modified with each click.

    The following is my code:

    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    import sys
    
    
    class FirstWindow(QMainWindow):
        def __init__(self):
            super(FirstWindow, self).__init__()
    
            self.setGeometry(500, 600, 600, 1000)
    
            self.scroll_area = QScrollArea(self)
            self.scroll_area.setGeometry(100, 300, 400, 400)
            self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
            self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.scroll_area.setWidgetResizable(True)
    
            self.push_button = QPushButton(self)
            self.push_button.setGeometry(200, 100, 50, 50)
            self.push_button.setText("Next")
            self.push_button.clicked.connect(self.next)
    
            self.push_button = QPushButton(self)
            self.push_button.setGeometry(200, 150, 50, 50)
            self.push_button.setText("Back")
            self.push_button.clicked.connect(self.back)
    
            self.stacked_widget = QStackedWidget(self)
            self.stacked_widget.setGeometry(100, 300, 398, 398)
    
            self.scroll_area.setWidget(self.stacked_widget)
    
            self.layout_1 = QVBoxLayout()
            self.layout_2 = QVBoxLayout()
    
            self.scroll_widget1 = QWidget(self)
            self.scroll_widget1.setGeometry(100, 300, 398, 398)
    
    
            self.scroll_widget2 = QWidget(self)
            self.scroll_widget2.setGeometry(100, 300, 398, 398)
    
            self.stacked_widget.addWidget(self.scroll_widget1)
            self.stacked_widget.addWidget(self.scroll_widget2)
    
            self.scroll_widget1.setLayout(self.layout_1)
            self.scroll_widget2.setLayout(self.layout_2)
    
            for i in range(50):
                self.label = QLabel(self)
                self.label.setText("FIRST")
                self.layout_1.addWidget(self.label)
    
            for i in range(100):
                self.label = QLabel(self)
                self.label.setText("SECOND")
                self.layout_2.addWidget(self.label)
    
        def next(self):
            self.stacked_widget.setCurrentIndex(1)
            for i in range(70):
                self.label = QLabel(self)
                self.label.setText("FIRST")
                self.layout_1.addWidget(self.label)
    
        def back(self):
            self.stacked_widget.setCurrentIndex(0)
    
    def main():
        app = QApplication(sys.argv)
        win = FirstWindow()
        win.show()
        app.exec_()
    
    main()
    

    Thank you!

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 6 Jan 2021, 18:12 last edited by
      #2

      Hi and welcome to devnet,

      Which version of PyQt5 are you using ?
      On which platform ?

      AFAIR, QStackedWidget will use the size of the its biggest widget for its own size. If you want it to resize to the current one, you will have to manage that yourself.

      Note that you can also add a stretch after the last label to push them all up.

      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
      • D Offline
        D Offline
        deleted412
        wrote on 6 Jan 2021, 18:40 last edited by deleted412 1 Jun 2021, 18:40
        #3

        I am using PyQt5 version 5.15. I am using PyCharm as my IDE.

        Thank you. How do I resize the current widget? And sorry, I am very new to PyQt, does the stretch help the layout?

        I am thinking instead to use two different QScrollAreas, and show() and hide() both of them in order to accomplish having two different widgets. Is this also acceptable? Thank you

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 6 Jan 2021, 18:45 last edited by
          #4

          It's up to you but I do not see any issue in using several QScrollArea. That will likely make your coding easier.

          As for the resizing, the idea is to react when the current widget changes and trigger a resize then. However, since you are starting having your big sized widget each in a QScrollArea will be less trouble.

          Since you are using a QMainWindow, you should also set your widget stack as central widget rather than manually placing it.

          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
          • D Offline
            D Offline
            deleted412
            wrote on 6 Jan 2021, 19:30 last edited by
            #5

            Thanks for your help. Is it better practice to make separate classes for my QScrollAreas? Or can I include this code in my class of QMainWindow?

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 6 Jan 2021, 19:36 last edited by
              #6

              I'd say it depends on what you are going to develop. For your current tests you can do everything in your QMainWindow.

              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
              • D Offline
                D Offline
                deleted412
                wrote on 6 Jan 2021, 19:49 last edited by
                #7

                Thanks. For practice, I'm attempting to create a different QScrollArea in a separate class. How would I then attach this separate class to my QMainWindow?

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 6 Jan 2021, 19:51 last edited by
                  #8

                  If you implement it in a separate Python file, the same way you do for other widgets, import and use.

                  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
                  • D Offline
                    D Offline
                    deleted412
                    wrote on 6 Jan 2021, 20:12 last edited by
                    #9

                    Okay, I understand. However, how would I accomplish this if I were to add these classes in the same Python file, i.e., in the same main() function as my QMainWindow?

                    For example, I would like to pass a variable from my QMainWindow into a separate QScrollArea class. However, I would like the QScrollArea to then be attached to my QMainWindow, which does not happen in my test:

                    from PyQt5.QtGui import *
                    from PyQt5.QtWidgets import *
                    from PyQt5.QtCore import *
                    import sys
                    
                    
                    class FirstWindow(QMainWindow):
                        def __init__(self):
                            super(FirstWindow, self).__init__()
                    
                            self.setGeometry(500, 600, 600, 1000)
                    
                            self.first = First("Test String")
                    
                    
                    class First(QScrollArea):
                        def __init__(self, label_text):
                            super(First, self).__init__()
                    
                            self.setGeometry(100, 300, 400, 400)
                            self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
                            self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
                            self.setWidgetResizable(True)
                    
                            self.layout_1 = QVBoxLayout()
                    
                            self.scroll_widget1 = QWidget(self)
                            self.scroll_widget1.setGeometry(100, 300, 398, 398)
                    
                            self.scroll_widget1.setLayout(self.layout_1)
                    
                            self.setWidget(self.scroll_widget1)
                    
                    
                            for i in range(50):
                                self.label = QLabel(self)
                                self.label.setText(label_text)
                                self.layout_1.addWidget(self.label)
                    
                            self.show()
                    
                    
                    def main():
                        app = QApplication(sys.argv)
                        win = FirstWindow()
                        win.show()
                        app.exec_()
                    
                    main()
                    
                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on 6 Jan 2021, 20:18 last edited by
                      #10

                      Do not call show in your subclass constructor, it's not its role to say when to be shown.

                      I think you are over engineering things. A custom widget that you create should be used in the same manner as any provided by Qt.

                      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
                      • D Offline
                        D Offline
                        deleted412
                        wrote on 6 Jan 2021, 20:48 last edited by
                        #11

                        Thanks! So this example is acceptable/best practice when incorporating other widgets into my QMainWindow?

                        from PyQt5.QtGui import *
                        from PyQt5.QtWidgets import *
                        from PyQt5.QtCore import *
                        import sys
                        
                        
                        class FirstWindow(QMainWindow):
                            def __init__(self):
                                super(FirstWindow, self).__init__()
                        
                                self.setGeometry(500, 600, 600, 1000)
                        
                                self.scroll = QScrollArea(self)
                                self.scroll.setGeometry(100, 300, 400, 400)
                                self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
                                self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
                                self.scroll.setWidgetResizable(True)
                        
                                self.layout_1 = QVBoxLayout()
                        
                                self.scroll_widget1 = QWidget(self)
                                self.scroll_widget1.setGeometry(100, 300, 398, 398)
                        
                                self.scroll_widget1.setLayout(self.layout_1)
                        
                                self.scroll.setWidget(self.scroll_widget1)
                        
                                for i in range(50):
                                    self.label = QLabel(self)
                                    self.label.setText("Test String")
                                    self.layout_1.addWidget(self.label)
                        
                        def main():
                            app = QApplication(sys.argv)
                            win = FirstWindow()
                            win.show()
                            app.exec_()
                        
                        main()
                        
                        1 Reply Last reply
                        0
                        • S Offline
                          S Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on 7 Jan 2021, 10:16 last edited by
                          #12

                          You forgot to set your QScrollArea as central 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
                          1
                          • D Offline
                            D Offline
                            deleted412
                            wrote on 7 Jan 2021, 17:25 last edited by
                            #13

                            Thanks for the reminder. Why would you say that this has to be the central widget? Suppose I add a title to the GUI, this would not be the central widget?

                            1 Reply Last reply
                            0
                            • S Offline
                              S Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on 7 Jan 2021, 17:50 last edited by
                              #14

                              Just because you are using a QMainWindow as base class of your main widget. Otherwise, you should put it in a layout in your main 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

                              1/14

                              6 Jan 2021, 16:04

                              • Login

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