【问题标题】:QTableWidgetItem return item type (pyqt)QTableWidgetItem 返回项目类型(pyqt)
【发布时间】:2016-06-14 08:28:26
【问题描述】:

我正在使用 Qt 和 python(以及 pyqt)编写一个 QGIS 插件。

在 QtDesigner 中,我有一个 QTableWidget 对象,如果有办法获取列项类型,我真的很苦恼。

例如,在下表中:

我输入了一些用户可以编辑的默认参数。此外,用户可以添加具有其他值的其他行。

我想知道我是否可以 force 输入列数据类型(例如 float、int、string)并将此信息作为我可以使用的列表(或任何其他 python 对象)获取python代码。

我没有在 Qt API 中找到有用的东西。

你知道有没有办法做到这一点?

编辑

感谢@rbaleksandar 的回答,我又迈出了一步。

这段代码如下:

l = []
for i in range(self.tableWidget.columnCount()):
    itm = self.tableWidget.item(0,i)
    l.append(itm.type())

但是,即使表格的第一行填充了某个数字,带有 QVarianttranslated 值的结果列表也是由零组成的:

l = [0, 0, 0, 0, 0, 0, 0, 0, 0]

我发现 QVariant 类型与数字相关联(2 代表 Int,6 代表 Double,10 代表字符串)所以我预计 l 会填充这些数字,所以:

l = [2, 6, 6, 6, 6, 6, 6, 6, 6]

我错过了什么吗?

再次感谢

【问题讨论】:

  • 您能否提供一个简单的工作示例来概述您的问题,以便其他人(包括我自己)不必键入整个应用程序,而是使用您的代码?
  • 您想限制用户可以在单元格中输入的内容吗?例如,只允许他们输入整数和浮点数?
  • @Brendan Abel,如果可能的话。

标签: python qt types pyqt qtablewidget


【解决方案1】:

仔细查看构造函数,更准确地说是type 参数:

QTableWidgetItem::QTableWidgetItem(int type = Type)
QTableWidgetItem::QTableWidgetItem(const QString & text, int type = Type)
QTableWidgetItem::QTableWidgetItem(const QIcon & icon, const QString & text, int type = Type)

另外看看QTableWidgetItem::UserType(例如发帖here

【讨论】:

  • 感谢您的回答。无论如何,我无法获得包含 QVariant tyoe 数量的列表,请参阅问题的编辑
【解决方案2】:

QTableWidget 将自动为most common data types 提供正确的编辑器。但要使其正常工作,您必须使用EditRole 将值添加到带有setData 的表格小部件项。

这是一个简单的演示:

from PyQt4 import QtCore, QtGui

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.table = QtGui.QTableWidget(3, 6, self)
        self.button = QtGui.QPushButton('Get Value', self)
        self.edit = QtGui.QLineEdit(self)
        self.edit.setReadOnly(True)
        self.button.clicked.connect(self.handleButton)
        layout = QtGui.QGridLayout(self)
        layout.addWidget(self.table, 0, 0, 1, 2)
        layout.addWidget(self.button, 1, 0, 1, 1)
        layout.addWidget(self.edit, 1, 1, 1, 1)
        # populate the table
        data = ['text', 1, 0.25, True,
                QtCore.QDate.currentDate(),
                QtCore.QTime.currentTime()]
        for row in range(3):
            for column, value in enumerate(data):
                item = QtGui.QTableWidgetItem()
                item.setData(QtCore.Qt.EditRole, value)
                self.table.setItem(row, column, item)

    def handleButton(self):
        try:
            item = self.table.selectedItems()[0]
            self.edit.setText('Value: %s, Type: %s' %
                (item.text(), type(item.data(QtCore.Qt.EditRole))))
        except IndexError:
            self.edit.clear()

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 700, 200)
    window.show()
    sys.exit(app.exec_())

【讨论】:

  • 太棒了! - 多年来,我一直在寻找一种方法来从按钮更新表格项目并获得各种基于线程的悲伤。这要简单得多。
【解决方案3】:

QTableWidgetItem 构造函数的type 参数只是 区分某些项目的一种方式,它不会使Qt 以任何不同的方式显示数据或进行类型转换或任何事情像那样。例如,您可以选择将type=1001 用于int 单元格,将type=1002 用于float 单元格,但您仍然需要自行从int/float <-> string 进行转换。

您可以使用data() 方法和自定义用户角色(或仅将QTableWidgetItem 子类化并将额外数据存储为属性)将几乎所有数据存储在QTableWidgetItem 上。但无论您在项目上存储什么额外数据,项目都需要向用户显示 something。您可以在display role 上设置字符串数据(这是setText() 所做的),或者使用QItemDelegate 在每个项目单元格上手动绘制一些东西。

您要做的是在项目上设置int/float 数据,但显示它们的字符串表示,并允许用户编辑数据。

这通常通过QItemDelegate 完成。这是可以做到的一种方法。

MY_DATA_ROLE = QtCore.Qt.UserRole + 1
INT_TYPE = QtGui.QTableWidgetItem.UserType + 1
FLOAT_TYPE = QtGui.QTableWidgetItem.UserType + 2


class MyFloatIntDelegate(QtGui.QItemDelegate):

    def __init__(self, parent, table):
        super(MyFloatIntDelegate, self).__init__(parent)
        self.table = table

    def paint(self, painter, option, index):
        item = self.table.itemFromIndex(index)
        # This ensures the table is always displaying
        # the int/float value stored in the custom data role.
        if item and item.text() != str(item.data(MY_DATA_ROLE)):
            item.setText(str(item.data(MY_DATA_ROLE)))
        super(MyFloatIntDelegate, self).paint(painter, option, index)

    def createEditor(self, parent, option, index):
        editor = None
        item = self.table.itemFromIndex(index)
        if item:
            # Is this an int item?
            if item.type() == INT_TYPE:
                editor = QtGui.QSpinBox(parent)
                # Set the min/max as appropriate
                editor.setRange(0, 100)  
            # or a float item?
            elif item.type() == FLOAT_TYPE:
                editor = QtGui.QDoubleSpinBox(parent)
                # Set the min/max as appropriate
                editor.setRange(0, 100)
        return editor

    def setEditorData(self, editor, index):
        item = self.table.itemFromIndex(index)
        if item:        
            if item.type() == INT_TYPE:
                editor.setValue(item.data(MY_DATA_ROLE))
            elif item.type() == FLOAT_TYPE:
                editor.setValue(item.data(MY_DATA_ROLE))

    def setModelData(self, editor, model, index):
        item = self.table.itemFromIndex(index)
        if item:
            item.setData(MY_DATA_ROLE, editor.value())
            item.setText(str(editor.value()))



class MyWidget(QtGui.QWidget):

    def __init__(self):
        ...
        self.table = QtGui.QTableWiget(self)
        self.delegate = MyIntFloatDelegate(self, self.table)
        self.table.setItemDelegate(self.delegate)

        # Creating Items
        vals = [1, 3.5, 6.6, 1.0, 1.0]
        row = 0
        self.table.setColumnCount(len(vals))
        self.table.setRowCount(1)
        for col, val in enumerate(vals):
            item_type = INT_TYPE if isinstance(val, int) else FLOAT_TYPE
            item = QtGui.QTableWidgetItem(item_type)
            item.setData(MY_DATA_ROLE, val)
            self.table.setItem(row, col, item)

        # Getting data
        vals = []
        for col in range(len(vals)):
            item = self.table.item(row, col)
            val = item.data(MY_DATA_ROLE)
            vals.append(val)

您也可以省略使用type 值,而只为每种不同类型子类QTableWidgetItem,并在QItemDelegate 中进行isinstance() 检查,而不是检查type() 值。在这种情况下,您也可以只将int/float 值存储为text 数据,而不是创建MY_DATA_ROLE 自定义角色,并在需要数据值时将文本数据来回转换为int/float 值。当然,对于比int/float 值更复杂的数据,通常无法做到这一点,因此使用自定义数据角色(或子类QTableItemWidgets 上的属性)更灵活,可以在更多情况下使用。

【讨论】:

  • 哇!我会试一试!谢谢
猜你喜欢
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多