How to set a data object on a widget that does not have the setData () method

advertisements

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?


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).