为什么 QComboBox.findData() 不接受对象作为输入?

Why doesn't QComboBox.findData() accept an object as input?

我将对象作为 UserData 附加到 QStandardItem,该对象被添加到 QComboBox 模型。如果我随后使用 findData() 方法搜索它,我将得不到任何结果。如果我对一个简单的 int 做同样的事情,我会得到一个结果。我想这是 PySide 相关的,但我在源代码中找不到包装器。这是一个(有点)最小的例子:

import sys
from PySide import QtGui

class Foo(object):
    def __init__(self, value):
        self.value = value


class MyCombo(QtGui.QWidget):
    def __init__(self, *args):
        QtGui.QWidget.__init__(self, *args)

        combo = QtGui.QComboBox()
        combo.addItem(str(1), Foo(1))
        combo.addItem(str(2), 2)

        data = combo.itemData(0)
        print(data)  # prints the object repr
        print(combo.findData(data))  # returns -1 -> not found

        data = combo.itemData(1)
        print(data)  # prints 2
        print(combo.findData(data))  # returns 1 -> found

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    w = MyCombo()
    w.show()
    sys.exit(app.exec_())

为什么对象的 findData() return -1?任何关于可以搜索的内容的提示都将受到赞赏!

QT C++ doc 提供了解释。这是 findData 的定义,强调我的:

int QComboBox::findData(const QVariant & data, int role = Qt::UserRole, Qt::MatchFlags flags = static_cast ( Qt::MatchExactly | Qt::MatchCaseSensitive )) const

组合框中的数据只能是QVariant,也就是"a union for the most common Qt data types"。所以data只能是普通的Qt数据类型,不包括正则pythonclass。

不过,数据可以是QtCore.QObject,所以你的问题很容易解决:

class Foo(QtCore.QObject):
    def __init__(self, value,parent=None):
        super(Foo,self).__init__(parent)
        self.value = value

class MyCombo(QtGui.QWidget):
    def __init__(self, *args):
        QtGui.QWidget.__init__(self, *args)

        combo = QtGui.QComboBox()
        combo.addItem(str(1),Foo(1,self) )

        data = combo.itemData(0)
        print("data",data)  # prints the object repr
        print(combo.findData(data))  # returns 0 -> found

注意:QVariant 在 C++ 中使用,因为您需要用类型定义每个值(如 int i=0;)。在 python 中,您不需要这个,因为值可以随时更改类型。所以在 PySide 中,QVariant 没有实现,而是使用常规的 python 类型或 Qt 类型。

也不适合我。

我将 QComboBox 子类化以自己编写 findData 方法:

from PySide import QtGui


class QComboBox(QtGui.QComboBox):
    def findData(self, data):
        for index in range(self.count()):
            if self.itemData(index) == data:
                return index
        return -1