Python 动态QTableWidget上的跨列单元格验证
动态表上单元验证的推荐方法 场景:我有一个QDialog,根据不同的下拉选择动态添加一个或多个表。由于表是动态添加的,标准单元格单击信号是不够的。它只提供行和列,我需要知道除了行和列之外,还单击了哪个表。更具体地说,我有两个整数值的列。当其中一列中的单元格发生更改时,它们必须在有效范围内,并且第二列中单元格的值必须>=第一列中单元格的值 我对Python相当陌生,但我的想法是,我需要创建一个类,该类使用我需要的附加信息扩展QTableWidgetItem,并发送一个自定义信号,然后将其连接到对话框中的一个插槽。我尝试了以下代码的几种变体,但无法完全正确:Python 动态QTableWidget上的跨列单元格验证,python,python-2.7,pyqt,pyqt4,qtablewidget,Python,Python 2.7,Pyqt,Pyqt4,Qtablewidget,动态表上单元验证的推荐方法 场景:我有一个QDialog,根据不同的下拉选择动态添加一个或多个表。由于表是动态添加的,标准单元格单击信号是不够的。它只提供行和列,我需要知道除了行和列之外,还单击了哪个表。更具体地说,我有两个整数值的列。当其中一列中的单元格发生更改时,它们必须在有效范围内,并且第二列中单元格的值必须>=第一列中单元格的值 我对Python相当陌生,但我的想法是,我需要创建一个类,该类使用我需要的附加信息扩展QTableWidgetItem,并发送一个自定义信号,然后将其连接到对话
class SmartCell(QtCore.QObject):
valueChanged = QtCore.pyqtSignal(str) # Signal to be emitted when value changes.
def __init__(self, tbl, rowname, colname, value):
QtGui.QTableWidgetItem.__init__(self)
self.tbl_name = tbl
self.row_name = rowname
self.col_name = colname
# self.setText(value)
self.__value = value
@property
def value(self):
return self.__value
@value.setter
def value(self, value):
if self.__value != value:
self.__value = value
# self.setText(value)
signal = self.tbl_name + ":" + self.row_name + ":" + self.col_name + ":" + self.text()
self.valueChanged.emit(signal)
然后在对话框中,将SmartCell引用导入为sCell后:
item = sCell(obj_name, f.part_name, "start_frame", str(f.start_frame))
item.valueChanged.connect(self.frame_cell_changed)
tbl.setItem(rowcounter, 1, item)
item = sCell(obj_name, f.part_name, "end_frame", str(f.end_frame))
item.valueChanged.connect(self.frame_cell_changed)
tbl.setItem(rowcounter, 2, item)
验证委托应该做什么的任务变得太复杂了,而不是对QTableWidgetItems使用创建验证后逻辑
import random
from PyQt4 import QtCore, QtGui
class LimistDelegate(QtGui.QStyledItemDelegate):
def createEditor(self, parent, option, index):
editor = super(LimistDelegate, self).createEditor(parent, option, index)
if index.column() in (1, 2):
editor = QtGui.QSpinBox(parent)
return editor
def setEditorData(self, editor, index):
if index.column() in (1, 2):
m = 0 if index.column() == 1 else index.sibling(index.row(), 1).data()
M = index.sibling(index.row(), 2).data() if index.column() == 1 else 360
if hasattr(m, 'toPyObject'):
m = m.toPyObject()
if hasattr(M, 'toPyObject'):
M = M.toPyObject()
editor.setMinimum(m)
editor.setMaximum(M)
super(LimistDelegate, self).setEditorData(editor, index)
def create_table():
nrows, ncols = random.randrange(3, 6), 3
table = QtGui.QTableWidget(nrows, ncols)
for r in range(nrows):
text = "description {}".format(r)
a = random.randrange(0, 180)
b = random.randrange(a, 360)
for c, val in enumerate([text, a, b]):
it = QtGui.QTableWidgetItem()
it.setData(QtCore.Qt.DisplayRole, val) # set data on item
table.setItem(r, c, it)
return table
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
vlay = QtGui.QVBoxLayout(self)
for _ in range(4):
table = create_table()
delegate = LimistDelegate(table) # create delegate
table.setItemDelegate(delegate) # set delegate
vlay.addWidget(table)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
1) 你可以解释QComboBox的动力学,2)你说第一列从a到b,比如说从2到10,如果你放5,那么第二列的值应该是6到更多,比如说取7,现在把第一列的值改为8,7会发生什么:该值应该被删除、保持还是设置为8?3)添加的表有多少行?假设A列中的初始值为0,B列中的初始值为18。如果我试图将A列中的值更改为20(或任何大于18的值),则A列会将输入的值重置为18。从B栏的角度来看;如果A列的初始值为20,B列的初始值为99。如果用户试图将B列的值更改为10,则验证会将值更改为20,因为B列可能不小于A列。3)行号是可变的。它们基于从web API返回的结果,根据提供的SKU不同而有所不同。好的,问题2和3已解决(在我的示例中,行数将是随机的),问题1?QComboBox是否仅用于选择添加的QTableWidget的数量?感谢您的帮助。单独来看,提供的解决方案是有效的。对于我来说,第1列包含一个描述,整数值实际上在第2列和第3列中。我假设这意味着我需要修改setEditorData中的m和m行是否正确?什么叫委托createEditor方法?@littleGreenDude当你想编辑视图时,调用委托来创建编辑器,实际上你的视图已经有了委托,但这是默认的。我建议你阅读: