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. Unable to add a widget to a QScrollArea object dynamically

Unable to add a widget to a QScrollArea object dynamically

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 3 Posters 1.9k Views
  • 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.
  • sunshk1227S Offline
    sunshk1227S Offline
    sunshk1227
    wrote on last edited by
    #1

    Hi, guys! I met two problems when I want to add a widget to a QScrollArea object dynamically. When I comment that line, the new widget I want to add could not be displayed on the screen. Moreover, I found that I could not scroll that area on the screen.

    Thank you very much for any help!

    from PyQt5.QtWidgets import *
    
    
    class MyList(QScrollArea):
        def __init__(self):
            super().__init__()
            self._widget = QWidget()
            self._layout = QVBoxLayout()
            
            # If I comment this line, MyButton._add function will not work, and the screen will not display new widget.
            self._layout.addWidget(QPushButton('test'))
    
            # set layout and widget
            self._widget.setLayout(self._layout)
            self.setWidget(self._widget)
    
            # display settings
            self.setMinimumSize(1024, 540)
    
    
    class MyButton(QPushButton):
        def __init__(self, text, _list):
            super().__init__(text=text)
            self._list = _list
            self.clicked.connect(self._add)
        
    
        def _add(self):
            self._list._layout.addWidget(QPushButton('test'))
    
    
    class MainWindow(QWidget):
        def __init__(self):
            super().__init__()
            self._layout = QVBoxLayout()
            self._my_list = MyList()
            self._my_button = MyButton(text='Add', _list=self._my_list)
            self._layout.addWidget(self._my_list)
            self._layout.addWidget(self._my_button)
    
            # set layout
            self.setLayout(self._layout)
    
            # display settings
            self.setWindowTitle('My Demo')
    
    
    def main():
        app = QApplication([])
        main_window = MainWindow()
    
        main_window.show()
        app.exec_()
    
    
    if __name__ == "__main__":
        main()    
    
    jsulmJ 1 Reply Last reply
    0
    • sunshk1227S Offline
      sunshk1227S Offline
      sunshk1227
      wrote on last edited by
      #9

      I figure out the reason with the help of @T.sagiv.
      The solution is that I have to adjust the scrollarea. Just replace self.setMinimumSize(1024, 540) with self.setWidgetResizable(True).

      1 Reply Last reply
      2
      • sunshk1227S sunshk1227

        Hi, guys! I met two problems when I want to add a widget to a QScrollArea object dynamically. When I comment that line, the new widget I want to add could not be displayed on the screen. Moreover, I found that I could not scroll that area on the screen.

        Thank you very much for any help!

        from PyQt5.QtWidgets import *
        
        
        class MyList(QScrollArea):
            def __init__(self):
                super().__init__()
                self._widget = QWidget()
                self._layout = QVBoxLayout()
                
                # If I comment this line, MyButton._add function will not work, and the screen will not display new widget.
                self._layout.addWidget(QPushButton('test'))
        
                # set layout and widget
                self._widget.setLayout(self._layout)
                self.setWidget(self._widget)
        
                # display settings
                self.setMinimumSize(1024, 540)
        
        
        class MyButton(QPushButton):
            def __init__(self, text, _list):
                super().__init__(text=text)
                self._list = _list
                self.clicked.connect(self._add)
            
        
            def _add(self):
                self._list._layout.addWidget(QPushButton('test'))
        
        
        class MainWindow(QWidget):
            def __init__(self):
                super().__init__()
                self._layout = QVBoxLayout()
                self._my_list = MyList()
                self._my_button = MyButton(text='Add', _list=self._my_list)
                self._layout.addWidget(self._my_list)
                self._layout.addWidget(self._my_button)
        
                # set layout
                self.setLayout(self._layout)
        
                # display settings
                self.setWindowTitle('My Demo')
        
        
        def main():
            app = QApplication([])
            main_window = MainWindow()
        
            main_window.show()
            app.exec_()
        
        
        if __name__ == "__main__":
            main()    
        
        jsulmJ Online
        jsulmJ Online
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #2

        @sunshk1227 said in Unable to add a widget to a QScrollArea object dynamically:

        When I comment that line, the new widget I want to add could not be displayed on the screen

        Of course not. But you did not explain what happens if you do NOT comment it out. So, what is actually the problem?

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        sunshk1227S 1 Reply Last reply
        0
        • jsulmJ jsulm

          @sunshk1227 said in Unable to add a widget to a QScrollArea object dynamically:

          When I comment that line, the new widget I want to add could not be displayed on the screen

          Of course not. But you did not explain what happens if you do NOT comment it out. So, what is actually the problem?

          sunshk1227S Offline
          sunshk1227S Offline
          sunshk1227
          wrote on last edited by
          #3

          @jsulm Hi, sorry I was not clear. When I comment that out, nothing happens if I click the "Add" button. But I print the number of the widget in main_window._my_list._layout.count(), the number increases correctly.

          jsulmJ 1 Reply Last reply
          0
          • sunshk1227S sunshk1227

            @jsulm Hi, sorry I was not clear. When I comment that out, nothing happens if I click the "Add" button. But I print the number of the widget in main_window._my_list._layout.count(), the number increases correctly.

            jsulmJ Online
            jsulmJ Online
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #4

            @sunshk1227 Try to call show() on new buttons:

            def _add(self):
                b = QPushButton('test')
                self._list._layout.addWidget(b)
                b.show()
            

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            sunshk1227S 1 Reply Last reply
            0
            • jsulmJ jsulm

              @sunshk1227 Try to call show() on new buttons:

              def _add(self):
                  b = QPushButton('test')
                  self._list._layout.addWidget(b)
                  b.show()
              
              sunshk1227S Offline
              sunshk1227S Offline
              sunshk1227
              wrote on last edited by
              #5

              @jsulm Hi, thank you for your help! But it seems that it does not work.

              (By the way, if I do NOT comment it out, a new button will be displayed on the screen when I click the "Add" button...)

              jsulmJ 1 Reply Last reply
              0
              • sunshk1227S sunshk1227

                @jsulm Hi, thank you for your help! But it seems that it does not work.

                (By the way, if I do NOT comment it out, a new button will be displayed on the screen when I click the "Add" button...)

                jsulmJ Online
                jsulmJ Online
                jsulm
                Lifetime Qt Champion
                wrote on last edited by jsulm
                #6

                @sunshk1227 Strange.
                Not a solution for the problem, but an improvement idea: instead of exposing internals of the MyList class (_layout) to the outside world you should make it private and add a method to add new widgets (like buttons).

                class MyList(QScrollArea):
                    ...
                    def addWidget(self, widget):
                        self.__layoutaddWidget(widget)
                

                This way MyButton does not have to know where to add new buttons to the list:

                def _add(self):
                        self._list.addWidget(QPushButton('test'))
                

                You could improve your design even more if you remove self._list from MyButton completely and instead emit a signal in MyButton and connect it to a slot in MyList. This way MyButton and MyList do not have to know anything about each other.

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                sunshk1227S 1 Reply Last reply
                0
                • jsulmJ jsulm

                  @sunshk1227 Strange.
                  Not a solution for the problem, but an improvement idea: instead of exposing internals of the MyList class (_layout) to the outside world you should make it private and add a method to add new widgets (like buttons).

                  class MyList(QScrollArea):
                      ...
                      def addWidget(self, widget):
                          self.__layoutaddWidget(widget)
                  

                  This way MyButton does not have to know where to add new buttons to the list:

                  def _add(self):
                          self._list.addWidget(QPushButton('test'))
                  

                  You could improve your design even more if you remove self._list from MyButton completely and instead emit a signal in MyButton and connect it to a slot in MyList. This way MyButton and MyList do not have to know anything about each other.

                  sunshk1227S Offline
                  sunshk1227S Offline
                  sunshk1227
                  wrote on last edited by
                  #7

                  @jsulm Thank you very much for your suggestions! Got it. But I still have a question... should I further improve my design like this? (In this case, could you please tell me how to connect a function with an additional argument, where I marked by '?' in my code?)
                  Thank you again for your advice!

                  class MyList(QScrollArea):
                      ...
                      def _addWidget(self, widget):
                          self._layout.addWidget(widget)
                  
                  
                  class MyButton(QPushButton):
                      def __init__(self, text):
                          super().__init__(text=text)
                  
                  
                  class MainWindow(QWidget):
                      def __init__(self):
                          ...
                  	self._my_list = MyList()
                          self._my_button = MyButton(text='Add')
                          self._my_button.clicked.connect(self._my_list._addWidget(?))
                  	...
                      ...
                  ...
                  
                  jsulmJ 1 Reply Last reply
                  0
                  • sunshk1227S sunshk1227

                    @jsulm Thank you very much for your suggestions! Got it. But I still have a question... should I further improve my design like this? (In this case, could you please tell me how to connect a function with an additional argument, where I marked by '?' in my code?)
                    Thank you again for your advice!

                    class MyList(QScrollArea):
                        ...
                        def _addWidget(self, widget):
                            self._layout.addWidget(widget)
                    
                    
                    class MyButton(QPushButton):
                        def __init__(self, text):
                            super().__init__(text=text)
                    
                    
                    class MainWindow(QWidget):
                        def __init__(self):
                            ...
                    	self._my_list = MyList()
                            self._my_button = MyButton(text='Add')
                            self._my_button.clicked.connect(self._my_list._addWidget(?))
                    	...
                        ...
                    ...
                    
                    jsulmJ Online
                    jsulmJ Online
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by jsulm
                    #8

                    @sunshk1227 said in Unable to add a widget to a QScrollArea object dynamically:

                    self._my_button.clicked.connect(self._my_list._addWidget(?))

                    This is wrong, should be:

                    self._my_button.clicked.connect(self._my_list._addWidget)
                    

                    In this line you only connect the signal to the slot, you do not call the slot. Slot will be called as soon as signal is emitted.

                    class MyButton(QPushButton):
                        newWidget = pyqtSignal()
                        def __init__(self, text):
                            super().__init__(text=text)
                            self.clicked.connect(self._add)
                       
                        def _add(self):
                                newWidget.emit(QPushButton('test'))
                    
                    self._my_button.newWidget.connect(self._my_list._addWidget)
                    

                    Not sure this 100% correct as I don't use PyQt/PiSide :-)

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    JonBJ 1 Reply Last reply
                    2
                    • sunshk1227S Offline
                      sunshk1227S Offline
                      sunshk1227
                      wrote on last edited by
                      #9

                      I figure out the reason with the help of @T.sagiv.
                      The solution is that I have to adjust the scrollarea. Just replace self.setMinimumSize(1024, 540) with self.setWidgetResizable(True).

                      1 Reply Last reply
                      2
                      • jsulmJ jsulm

                        @sunshk1227 said in Unable to add a widget to a QScrollArea object dynamically:

                        self._my_button.clicked.connect(self._my_list._addWidget(?))

                        This is wrong, should be:

                        self._my_button.clicked.connect(self._my_list._addWidget)
                        

                        In this line you only connect the signal to the slot, you do not call the slot. Slot will be called as soon as signal is emitted.

                        class MyButton(QPushButton):
                            newWidget = pyqtSignal()
                            def __init__(self, text):
                                super().__init__(text=text)
                                self.clicked.connect(self._add)
                           
                            def _add(self):
                                    newWidget.emit(QPushButton('test'))
                        
                        self._my_button.newWidget.connect(self._my_list._addWidget)
                        

                        Not sure this 100% correct as I don't use PyQt/PiSide :-)

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

                        @jsulm said in Unable to add a widget to a QScrollArea object dynamically:

                        Not sure this 100% correct as I don't use PyQt/PiSide :-)

                        newWidget.emit(QPushButton('test'))

                        Whazzis? :)

                        jsulmJ 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @jsulm said in Unable to add a widget to a QScrollArea object dynamically:

                          Not sure this 100% correct as I don't use PyQt/PiSide :-)

                          newWidget.emit(QPushButton('test'))

                          Whazzis? :)

                          jsulmJ Online
                          jsulmJ Online
                          jsulm
                          Lifetime Qt Champion
                          wrote on last edited by
                          #11

                          @JonB You're the Python guy here :-) It was meant to emit a signal with a parameter.

                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                          JonBJ 1 Reply Last reply
                          0
                          • jsulmJ jsulm

                            @JonB You're the Python guy here :-) It was meant to emit a signal with a parameter.

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

                            @jsulm
                            Yeah but I was suprised at your parameter! Yours is emit newWidget(new QPushButton("test")), is that what you intended? I didn't really read what OP wanted :-; So you want to emit a signal which accepts an unplaced new widget, presumably the slot does something with it? Interesting!

                            jsulmJ 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @jsulm
                              Yeah but I was suprised at your parameter! Yours is emit newWidget(new QPushButton("test")), is that what you intended? I didn't really read what OP wanted :-; So you want to emit a signal which accepts an unplaced new widget, presumably the slot does something with it? Interesting!

                              jsulmJ Online
                              jsulmJ Online
                              jsulm
                              Lifetime Qt Champion
                              wrote on last edited by
                              #13

                              @JonB Yes, the emitter sends new widget to add via signal. The receiver adds it to its UI.

                              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