Search code examples
pyqtqt-designer

How to get list of widgets in pyqt?


I am designing a interface with QtDesigner and editing its functionalities with PyQt. One of the widgets that i created has several pushButtons and i want them all to have the property Checkable = True.

So currently what i am doing is:

class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()
        uic.loadUi('./my_widget.ui', self)
        self.pushButton_X.setCheckable(True)
        self.pushButton_Y.setCheckable(True)
        self.pushButton_Z.setCheckable(True)
        self.pushButton_ETC.setCheckable(True)
        self.show()

Is there any way i can do something like:

pushbuttons_list = self.get_all_pushbuttons()
for i in pushbuttons_list:
    i.setCheckable(True)

?

Im trying the answers to this question but i keep getting

>  File "./testing_class.py", line 12, in __init__
    items = (self.layout.itemAt(i) for i in range(self.layout.count())) 
AttributeError: 'builtin_function_or_method' object has no attribute 'count'

Solution

  • Your example failed because all Qt properties can be accessed by calling the attribute (see the parentheses used for self.layout()):

    items = (self.layout().itemAt(i) for i in range(self.layout().count()))
    

    Note that this will only get access to the layout items, not the widgets they might (or might not) contain. For this, using comprehensions will only complicate things unnecessarily, as one-liners should be used only as long as they keep the code readable; the comprehension above is already complex enough, and since you will need to cycle through all items anyway, there's little use in it. Just use a for loop, which is far more readable:

    for i in range(self.layout().count()):
        widget = self.layout().itemAt(i).widget()
        if isinstance(widget, QPushButton):
            widget.setCheckable(True)
    

    Note that if you have several buttons that you want checkable and you are doing this only to avoid manually setting the checkable property for all of them, you can just use the extended selection mode that is common for all UI elements that allow selection by keeping pressed Ctrl when clicking multiple objects.
    The property editor will automatically show all common properties for the selected widgets, and apply the changed property to all of them.


    Another option is to use findChildren():

    for button in self.findChildren(QPushButton, Qt.FindDirectChildrenOnly):
        button.setCheckable(True)
    

    The Qt.FindDirectChildrenOnly flag is required whenever you have complex layouts that have nested widgets containing other buttons, if you remove that you will find any push button that exists inside the window (or the widget referenced as self).


    Finally, buttons can be part of a QButtonGroup, which can also be created in Designer. Just select all buttons (as explained above), right click on one of them and select "Assign to button group", and then:

    for button in self.buttonGroup.buttons():
        button.setCheckable(True)
    

    Note that the self.buttonGroup above is the object name assigned by Designer, if you change it or you create more than one, ensure that the reference matches it.