如何根据表QTableWidget的第一个单元格中的值将数据集加载到其他单元格中?



用户将数据驱动到表的第一个单元格中,该单元格通过自动完成从数据库中拉出。但是我怎么知道他已经编辑完了呢?我是否需要从这个单元格中获取数据并将剩余的数据上传到其他单元格?

class MasterWorkPlace(QMainWindow):
# Master work place
def __init__(self, what_post, parent=None, flag=Qt.Window):
super().__init__(parent, flag)
uic.loadUi('ui/work_place_for_master.ui', self)
self.blanks_operations = ["Clean", "Cut", "Pl", "Angle cut", "Drill"]
self.postion_cell_box = QtWidgets.QComboBox()
self.what_post = what_post
self.what_job = ''.join(db.get_job_by_post(self.what_post)[0])
self.what_operat = ''.join(db.get_job_by_post(self.what_post)[1])
self.post_lbl.setText(self.what_post)
self.dateEdit.setDate(QtCore.QDate.currentDate())  # Setup current date
self.dateEdit.setDisplayFormat('dd.MM.yyyy')  # Date format
self.how_many_columns = 0
self.load_table_clmn()
self.add_str_btn.clicked.connect(self.add_str_to_table)  # Add str to table
self.main_table.itemChanged.connect(self.load_information_from_db)
def load_table_clmn(self):
# Load header to table
if self.what_operat in self.blanks_operations:
name_of_colmns = ["Pos", "Material", "Massa kg", "Done",
"Plan", "Total", "Remains"]
self.how_many_columns = len(name_of_colmns)
self.main_table.setColumnCount(self.how_many_columns)
self.main_table.setHorizontalHeaderLabels(name_of_colmns)
self.main_table.horizontalHeaderItem(0).setTextAlignment(QtCore.Qt.AlignVCenter
| QtCore.Qt.AlignHCenter)
for evr_column in range(0, self.how_many_columns):
self.main_table.horizontalHeaderItem(evr_column).setTextAlignment(QtCore.Qt.AlignVCenter
    | QtCore.Qt.AlignHCenter)
if evr_column == 0:
self.main_table.setColumnWidth(evr_column, 90)
else:
self.main_table.setColumnWidth(evr_column, 120)
def add_str_to_table(self):
# Add str to a table
quantity_clmn = self.str_to_table_sb.value()
postion_cell = QtWidgets.QLineEdit()
autocomplite_list = []
how_much_rows_was = self.main_table.rowCount()
for information in db.get_all_operations():
autocomplite_list.append(information[1])
for _ in range(0, quantity_clmn):
rowposition = self.main_table.rowCount()
self.main_table.insertRow(rowposition)
self.add_autocomplite_to_table(how_much_rows_was)
self.str_to_table_sb.setValue(1)
def add_autocomplite_to_table(self, last_row):
column = 0
not_edit_columns = [1, 2, 5, 6, 7]
if self.what_operat not in self.blanks_operations:
not_edit_columns = [1, 4, 5, 6]
for row in range(last_row, self.main_table.rowCount()):
# postion_cell = QtWidgets.QLineEdit()
done_cell_sb = QtWidgets.QSpinBox()
done_cell_sb_2 = QtWidgets.QSpinBox()
done_cell_sb.setMinimum(1)
done_cell_sb_2.setMinimum(1)
done_cell_sb.setMaximum(1000)
done_cell_sb_2.setMaximum(1000)
autocomplite_list = []
for information in db.get_all_operations():
autocomplite_list.append(information[1])
self.postion_cell_box.addItem(information[1])
self.postion_cell_box.setEditable(True)
# completer = QCompleter(autocomplite_list, postion_cell)
# postion_cell.setCompleter(completer)
for column in range(self.how_many_columns):
if column == 0:
self.main_table.setCellWidget(row, column, self.postion_cell_box)
elif column in not_edit_columns:
delegate = ReadOnlyDelegate(self.main_table)
self.main_table.setItemDelegateForColumn(column, delegate)
elif column == 3:
self.main_table.setCellWidget(row, column, done_cell_sb_2)
else:
self.main_table.setCellWidget(row, column, done_cell_sb)
def load_information_from_db(self):
if self.main_table.selectedIndexes():
row = self.main_table.currentIndex().row()
name_of_posit = self.main_table.model().index(row, 0).data()
print(name_of_posit)

我试图使用"itemChanged"方法,但我失败了,因为我在表中使用了不同的小部件(QComboBox)。我也看到了关于QAbstractItemDelegate.closeEditor()方法的粘贴,但我不明白如何为我的小部件连接这个。

谢谢你的帮助:)

索引部件("单元格部件"(对于QTableWidget)通常不允许与数据模型进行交互。它们只是"重叠的"。可能对底层模型一无所知的小部件

如果您需要显示编辑器,即使用户没有显式地开始编辑单元格,那么您需要调用openPersistentEditor()

注意Qt基于数据类型创建编辑器,这意味着您首先需要使用正确的类型正确设置值。QTableWidgetItem在其构造函数中不接受数值,因此您需要调用setData(Qt.DisplayRole, value)并在打开编辑器之前将项目添加到表中。

如果你需要更多的控制编辑器(如设置其范围),那么你必须创建自己的委托和覆盖createEditor():

class LimitSpinBoxDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
editor = super().createEditor(parent, option, index)
if isinstance(editor, QSpinBox):
editor.setRange(1, 1000)
return editor

然后为您希望在其中设置数值并希望限制范围的列设置委托:

class MasterWorkPlace(QMainWindow):
def __init__(self, what_post, parent=None, flag=Qt.Window):
# ...
self.spinBoxDelegate = LimitSpinBoxDelegate(self.main_table)
self.main_table.setItemDelegateForColumn(someColumn, self.spinBoxDelegate)

以上操作允许您直接使用视图的函数(包括itemChanged信号)并从模型访问数据,而不是试图从小部件获取数据。

注意:你应该只创建新的委托,如果他们的实例是分开的(例如,在构造函数中区分可能的spinbox范围),否则你应该只在有不同的视图时这样做,因为项目委托不能在视图之间共享。这意味着在for循环中创建一个新的ReadOnlyDelegate不仅毫无意义,而且是错误的:

  • 考虑到该循环也是嵌套的,因此为每一行调用多个setItemDelegateForColumn()是无用的;
  • 基于您的代码,"只读"列可以根据上下文而更改,但是一旦在列(或行)上设置了委托,它就会为整个列设置,这意味着之前设置的只读列仍然是只读的,除非您重置委托;使用父构造函数创建的
  • 对象将是持久的(并占用内存),直到父构造函数存在,即使未使用;您可能会创建数百或数千个您甚至没有使用的委托;

如果您想要阻止对特定项的编辑,那么创建该项并删除Qt.ItemIsEditable标志:

item = QTableWidgetItem()
item.setFlags(item.flags() & ~Qt.ItemIsEditable)
self.main_table.setItem(row, column, item)