PyQT: QTableWidget.setItemPrototype无效?

1 投票
1 回答
1862 浏览
提问于 2025-04-15 12:39

在一个QTableWidget里,我想把所有的数值都显示成只有两位小数。为此,我创建了一个QTableWidgetItem的子类。

class MyCell(QTableWidgetItem):
    def __init__(self, *args):
        QTableWidgetItem.__init__(self, *args)

    def clone(self):
        return MyCell()

    def data(self, role):
        t = QTableWidgetItem(self).data(role)
        if role == 0:
            if t.type() != 0:
                try:
                    a, b = str(t.toString()).split('.')
                    return QVariant( ".".join([a,b[:2]]))
                except:
                    return t
         return t

我看了文档,想着可以用类似这样的方式:

class MyDialog(QDialog):
    def __init__(self, parent=None):
         super(MyDialog, self).__init__(parent)

         self.table = QTableWidget()
         acell = MyCell()
         self.table.setItemPrototype(acell)

         self.table.setRowCount(5)
         self.table.setColumnCount(5)
         ....

但是这样做时,程序会时不时地崩溃。当我使用self.table.setItem这个方法时,就没有问题。任何建议都很感谢。

1 个回答

1

这里有两个问题。一个可能是你的代码有问题,另一个可能是PyQt本身的bug。

在你的data()方法实现中,你可能想写成这样:

def data(self, role):
    t = QTableWidgetItem.data(self, role)
    ...

这样做是调用了父类的data()方法,而不是创建一个新项目并调用它的data方法。

当你设置对话框时,可能需要保留对你的项目原型的引用:

def __init__(self, parent=None):
    super(MyDialog, self).__init__(parent)

    self.table = QTableWidget()
    self.acell = MyCell()
    self.table.setItemPrototype(self.acell)

虽然Qt的文档说原型的所有权会转给表格小部件,但PyQt的绑定似乎并没有这样做,所以你需要防止原型被垃圾回收。

撰写回答