Making non-clickable widgets clickable

On the #pyqt channel on Freenode, xh asked if it was possible to make QLabel objects clickable without subclassing.

There are two ways to do this:

  1. Use event filters.
  2. Assign new methods to the labels.

These are shown below.

Event filters

The following example code shows how to use event filters to do this. It uses one filter object per label, which is created when the clickable() function is called with the widget that is to be click-enabled. The function returns a clicked() signal that actually belongs to the filter object. The caller can connect this signal to a suitable callable object.

   1 import sys
   2 from PyQt4.QtCore import *
   3 from PyQt4.QtGui import *
   4 
   5 def clickable(widget):
   6 
   7     class Filter(QObject):
   8     
   9         clicked = pyqtSignal()
  10         
  11         def eventFilter(self, obj, event):
  12         
  13             if obj == widget:
  14                 if event.type() == QEvent.MouseButtonRelease:
  15                     self.clicked.emit()
  16                     return True
  17             
  18             return False
  19     
  20     filter = Filter(widget)
  21     widget.installEventFilter(filter)
  22     return filter.clicked
  23 
  24 
  25 class Window(QWidget):
  26 
  27     def __init__(self, parent = None):
  28     
  29         QWidget.__init__(self, parent)
  30         
  31         label1 = QLabel(self.tr("Hello world!"))
  32         label2 = QLabel(self.tr("ABC DEF GHI"))
  33         label3 = QLabel(self.tr("Hello PyQt!"))
  34         
  35         clickable(label1).connect(self.showText1)
  36         clickable(label2).connect(self.showText2)
  37         clickable(label3).connect(self.showText3)
  38         
  39         layout = QHBoxLayout(self)
  40         layout.addWidget(label1)
  41         layout.addWidget(label2)
  42         layout.addWidget(label3)
  43     
  44     def showText1(self):
  45         print "Label 1 clicked"
  46     
  47     def showText2(self):
  48         print "Label 2 clicked"
  49     
  50     def showText3(self):
  51         print "Label 3 clicked"
  52 
  53 
  54 if __name__ == "__main__":
  55 
  56     app = QApplication(sys.argv)
  57     window = Window()
  58     window.show()
  59     sys.exit(app.exec_())

Assigning new methods

As xh pointed out, it should be possible to assign new event handler methods to instances of QLabel, and this should work as long as the labels were created in Python:

   1 import sys
   2 from PyQt4.QtGui import *
   3 
   4 class Window(QWidget):
   5 
   6     def __init__(self, parent = None):
   7     
   8         QWidget.__init__(self, parent)
   9         
  10         label1 = QLabel(self.tr("Hello world!"))
  11         label2 = QLabel(self.tr("ABC DEF GHI"))
  12         label3 = QLabel(self.tr("Hello PyQt!"))
  13         
  14         label1.mouseReleaseEvent = self.showText1
  15         label2.mouseReleaseEvent = self.showText2
  16         label3.mouseReleaseEvent = self.showText3
  17         
  18         layout = QHBoxLayout(self)
  19         layout.addWidget(label1)
  20         layout.addWidget(label2)
  21         layout.addWidget(label3)
  22     
  23     def showText1(self, event):
  24         print "Label 1 clicked"
  25     
  26     def showText2(self, event):
  27         print "Label 2 clicked"
  28     
  29     def showText3(self, event):
  30         print "Label 3 clicked"
  31 
  32 
  33 if __name__ == "__main__":
  34 
  35     app = QApplication(sys.argv)
  36     window = Window()
  37     window.show()
  38     sys.exit(app.exec_())

PyQtWiki: Making non-clickable widgets clickable (last edited 2009-10-19 13:45:19 by DavidBoddie)