Reputation: 19329
I need to connect data object (class instance) to QLabel
widget that doesn't have setData() method. Is there a way to extend QLabel so it supports data attachment?
Upvotes: 0
Views: 1148
Reputation: 7889
You can use the dynamic setProperty method to hide extra information inside Qt objects.
self.myqlabel.setProperty("answer", 42)
Then use the property method to retrieve the information later:
value = self.myqlabel.property("answer")
What is also nice about this technique.. you can store multiple pieces of data, just change the property string to whatever you want:
self.myqlabel.setProperty("name", "bruno mars")
Not sure, but this may be a Qt5 feature?
Upvotes: 0
Reputation: 11849
I would suggest subclassing. While @BlackJack's answer will work, it is generally considered poor form to "duck punch"/"monkey patch" as you open yourself up to problems. From wikipedia
Carelessly written or poorly documented monkey patches can lead to problems:
They can lead to upgrade problems when the patch makes assumptions about the patched object that are no longer true; if the product you have changed changes with a new release it may very well break your patch. For this reason monkey patches are often made conditional, and only applied if appropriate.
If two modules attempt to monkey patch the same method, one of them (whichever one runs last) "wins" and the other patch has no effect, unless monkey patches are written with a pattern like alias_method_chain.
They create a discrepancy between the original source code on disk and the observed behaviour that can be very confusing to anyone unaware of the patches' existence.
Even if monkey patching isn't used, some see a problem with the availability of the feature, since the ability to use monkey patching in a programming language is incompatible with enforcing strong encapsulation, as required by the object-capability model, between objects.
As such, subclassing is the preferred approach. Something like this, for example:
class MyLabel(QLabel):
def __init__(self, *args, **kwargs):
QLabel.__init__(self, *args, **kwargs)
self._data = None
def data(self):
return self._data
def setData(self, data):
self._data = data
This then matches Qt syntax of other classes.
You could also extend it to support storing data for multiple roles (like some other Qt classes)
class MyLabel(QLabel):
def __init__(self, *args, **kwargs):
QLabel.__init__(self, *args, **kwargs)
self._data = {}
def data(self, role = Qt.DisplayRole):
if role in self._data:
return self._data[role]
return None
def setData(self, data, role = Qt.DisplayRole):
self._data[role] = data
Obviously this is only for use by your Python code (Qt won't use it).
Upvotes: 1
Reputation: 4679
Have you tried to just assign the data to an attribute?
In [2]: from PyQt4 import QtCore, QtGui
In [3]: import sys
In [4]: app = QtGui.QApplication(sys.argv)
In [5]: label = QtGui.QLabel('Test')
In [6]: label.answer = 42
In [7]: label.answer
Out[7]: 42
Upvotes: 1