如何在没有setData()方法的小部件上设置数据对象

0 投票
3 回答
1044 浏览
提问于 2025-04-18 13:09

我需要把一个数据对象(类的实例)连接到一个QLabel控件上,但这个控件没有setData()这个方法。有没有办法扩展QLabel,让它支持数据的附加呢?

3 个回答

0

你可以使用动态的 setProperty 方法来隐藏 Qt 对象中的额外信息。

self.myqlabel.setProperty("answer", 42) 

然后可以用 property 方法来稍后获取这些信息:

value = self.myqlabel.property("answer")   

这个技巧还有个好处,就是你可以存储多条数据,只需要把属性字符串改成你想要的内容就行:

self.myqlabel.setProperty("name", "bruno mars") 

不太确定,但这可能是 Qt5 的一个功能?

1

你有没有试过直接把数据赋值给一个属性呢?

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
1

我建议使用子类化。虽然@BlackJack的回答也能解决问题,但通常来说,直接修改现有代码(也叫“猴子补丁”)是不太好的做法,因为这样可能会引发一些问题。来自维基百科的内容:

随意编写或文档不全的猴子补丁可能会导致一些问题:

  • 当补丁对被修改的对象的假设不再成立时,可能会导致升级问题;如果你修改的产品在新版本中发生了变化,补丁可能会失效。因此,猴子补丁通常会设置条件,只在合适的情况下应用。

  • 如果两个模块试图对同一个方法进行猴子补丁,最后执行的那个补丁会“胜出”,而另一个补丁则没有效果,除非猴子补丁是按照某种模式(比如alias_method_chain)编写的。

  • 它们会导致磁盘上的原始源代码和实际行为之间出现差异,这对那些不知道补丁存在的人来说可能会非常困惑。

即使不使用猴子补丁,有些人也会认为功能的可用性存在问题,因为在编程语言中使用猴子补丁的能力与对象能力模型所要求的对象之间强封装的原则是相互矛盾的。

因此,使用子类化是更好的选择。比如这样:

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

这样就能与其他类的Qt语法保持一致。

你还可以扩展它,以支持为多个角色存储数据(就像一些其他的Qt类一样)。

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

显然,这只是供你的Python代码使用(Qt不会使用它)。

撰写回答