Search code examples
pythonqteventspysideqwidget

Implement event handlers for QWidget and derived classes and avoid code duplication


I made a clickable QWidget by inheriting from it as follows in Python (using a Python-Qt binding):

class ClickableWidget(QtGui.QWidget):

    clicked = QtCore.Signal(QtGui.QMouseEvent)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def mousePressEvent(self, event):
        self.clicked.emit(event)

Of course more events and more signals could be implemented.

I want to add the same functionality to QLabel, QToolBar, .. This could of course be done easily the same way resulting in a lot of code duplication.

Is there a better alternative in the sense that there is minimal code duplication and the code is efficient and easy maintainable? What would be the most Qt-like/Pythonic way?

One alternative might be to install an event filter on the Qt-application(?) to filter for all events going to any of the desired widgets but this might get complex by itself having to differentiate between the target objects..


Solution

  • You could create a function to define the subclasses

    def createClickableSubclass(parent):
        class ClickableSubclass(parent):
            clicked_ = QtCore.Signal(QtGui.QMouseEvent)
    
            def __init__(self, *args, **kwargs):
                super(ClickableSubclass, self).__init__(*args, **kwargs)
    
            def mousePressEvent(self, event):
                self.clicked_.emit(event)
    
        return ClickableSubclass
    
    
    MyLabel = createClickableSubclass(QtGui.QLabel)
    MyToolBar = createClickableSubclass(QtGui.QToolBar)
    

    Edit: with reference to your comment, you would use the subclasses like this:

    aLabel = MyLabel('Label text')
    aLabel.setStyleSheet('color: yellow')