Search code examples
pythonpyqt4subclassqwidget

how to get subclassed QWidgets from QToolBox?


I wrote a few customized widget classes by subclassing QWidget. I created a few customized widgets using them and added them to a QToolBox.

class BaseWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        # initialize

    def mymethod():
        pass

class AWidget(BaseWidget):
    def __init__(self, parent=None):
        # initialize

    def mymethod():
        print "A"

class BWidget(BaseWidget):
    def __init__(self, parent=None):
        # initialize

    def mymethod():
        print "B"

Now I want to loop over all the widgets added to the QToolBox and call a method of these customized widgets:

class toolboxWidget(QtGui.QToolBox):
    def __init__(self, parent=None):
        super(toolboxWidget, self).__init__(parent=parent)
        a = AWidget(self)
        b = BWidget(self)
        self.addItem(a, "A")
        self.addItem(b, "B")

    def printMethod(self):
        for i in range(self.count()):
            self.widget(i).mymethod()

However, since widget() method of QToolBox only returns objects of QWidget type, when calling printMethod() of toolboxWidget object, it gives the following error:

AttributeError: 'QWidget' object has no attribute 'mymethod'.

Is there a way I can convert the QWidget returned by widget() to BaseWidget objects? Thanks.


Solution

  • After fixing all the obvious errors and omissions in your example code, I was able to get it working without any problems.

    If the QToolBox.widget method didn't return an instance of one of your BaseWidget subclasses, it would be a bug in PyQt (or sip).

    Here is a script that works for me using sip 4.15.4 and PyQt 4.10.3:

    from PyQt4 import QtCore, QtGui
    
    class BaseWidget(QtGui.QWidget):
        def __init__(self, parent=None):
            QtGui.QWidget.__init__(self, parent)
    
        def mymethod(self):
            pass
    
    class AWidget(BaseWidget):
        def __init__(self, parent=None):
            BaseWidget.__init__(self, parent)
    
        def mymethod(self):
            print "A"
    
    class BWidget(BaseWidget):
        def __init__(self, parent=None):
            BaseWidget.__init__(self, parent)
    
        def mymethod(self):
            print "B"    
    
    class Window(QtGui.QWidget):
        def __init__(self):
            QtGui.QWidget.__init__(self)
            self.toolbox = QtGui.QToolBox(self)
            a = AWidget(self.toolbox)
            b = BWidget(self.toolbox)
            self.toolbox.addItem(a, "A")
            self.toolbox.addItem(b, "B")
            self.button = QtGui.QPushButton('Test', self)
            self.button.clicked.connect(self.printMethod)
            layout = QtGui.QVBoxLayout(self)
            layout.addWidget(self.toolbox)
            layout.addWidget(self.button)
    
        def printMethod(self):
            for i in range(self.toolbox.count()):
                self.toolbox.widget(i).mymethod()
    
    if __name__ == '__main__':
    
        import sys
        app = QtGui.QApplication(sys.argv)
        window = Window()
        window.setGeometry(500, 300, 300, 300)
        window.show()
        sys.exit(app.exec_())