2016-03-01 73 views
1

我正在写一个QGIS插件使用Qt和python(以及pyqt)。QTableWidgetItem返回项目类型(pyqt)

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

例如,如下表所示:

enter image description here

我输入用户可以编辑一些缺省参数。此外,用户可以添加具有其他值的其他行。我想知道如果我可以得到强制列数据类型输入(例如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()) 

但是,即使在填充有一些数量的,用的QVariant 结果列表的表的第一行翻译值由零的:

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

我发现了与数字(2为中等,6为双和10弦乐)相关联的类型的QVariant所以预计l填充有这些数字,所以:

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

我错过了什么吗?

再次感谢

+1

你可以提供概括您的问题最小工作示例,这样其他人(包括我自己)不必键入整个应用程序,而是与您的代码工作? – rbaleksandar

+0

你想限制用户可以输入到单元格中的内容吗?例如,只允许他们输入整数和浮点数? –

+0

@Brendan Abel,如果有可能的话。 – matteo

回答

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(SO张贴here例如)

+0

感谢您的答案。无论如何,我无法获得QVariant tyoe数字列表,请参阅编辑 – matteo

0

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

可以使用data()方法和自定义用户角色(或只是继承QTableWidgetItem和存储额外的数据作为一个属性)存储在一个QTableWidgetItem几乎任何数据。但无论您存储在该物品上的任何额外数据如何,该物品都需要向用户显示某种东西。您需要在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并做isinstance()检查在QItemDelegate而不是检查type()值。在这种情况下,你也可以只存储int/float值作为text数据,而不是创建MY_DATA_ROLE自定义角色和文本数据,只要你想要的数据值转换来回int/float值。当然,这通常不能用比int/float值更复杂的数据完成,因此使用自定义数据角色(或子类型QTableItemWidgets上的属性)更灵活,可用于更多情况。

+0

哇!我会试一试!谢谢 – matteo

1

一个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_()) 
+0

太棒了! - 我一直在四处寻找尝试寻找从按钮更新表项并获得各种基于线程的悲伤的方法。这非常简单。 – Tim