QTableWidget内嵌QComboBox取值报AttributeError仅最后一行生效问题
问题原因
核心问题出在populate方法中表格填充逻辑的不合理操作,导致除最后一行外其余行的下拉框对象被意外回收/覆盖:
- 为放置
QComboBox的单元格重复设置空QTableWidgetItem:QTableWidget的同一个单元格不能同时存在Item和Cell Widget,你为1、6、7列调用setItem设置空Item的操作,会在表格刷新时覆盖/销毁已绑定的下拉框控件。 - 重复绑定Cell Widget:你把
setCellWidget操作放在下拉选项的遍历循环中,每次添加选项都重复绑定一次控件,不必要的重复操作会触发Qt内部对象管理异常。 - 逐次修改表格行数:你每次处理一行数据就调用
setRowCount逐次增加行数,会触发表格多次全局刷新,导致前面行已绑定的控件被意外回收。 - 若你开启了表格排序功能,QTableWidget默认排序只会移动单元格Item,不会同步移动绑定的Cell Widget,也会导致索引和控件不匹配。
修复方案
按以下逻辑修改populate方法即可解决:
- 清空表格后一次性设置总行数,不要逐次修改行数
- 移除给1、6、7列设置空Item的代码,下拉框所在列不需要绑定QTableWidgetItem
- 下拉选项全部添加完成后,再调用一次
setCellWidget绑定控件,不要放在循环内重复操作 - 取值时增加类型校验,避免异常崩溃
修正后的核心代码示例
def populate(self): self.ui.widget_unass_fights.clearContents() # 一次性设置总行数 total_rows = len(x) self.ui.widget_unass_fights.setRowCount(total_rows) for tablerow, row in enumerate(x): # 普通列正常设置Item self.ui.widget_unass_fights.setItem(tablerow, 0, QtWidgets.QTableWidgetItem(str(row[0]))) self.ui.widget_unass_fights.setItem(tablerow, 2, QtWidgets.QTableWidgetItem(str(row[2]))) self.ui.widget_unass_fights.setItem(tablerow, 3, QtWidgets.QTableWidgetItem(str(row[3]))) self.ui.widget_unass_fights.setItem(tablerow, 4, QtWidgets.QTableWidgetItem(str(row[4]))) self.ui.widget_unass_fights.setItem(tablerow, 5, QtWidgets.QTableWidgetItem(str(row[5]))) self.ui.widget_unass_fights.setItem(tablerow, 8, QtWidgets.QTableWidgetItem(str(row[8]))) # 第1列下拉框 combobox1 = QComboBox() for j in self.plane_list_combo: combobox1.addItem(j) combobox1.setCurrentText(row[1]) # 只绑定一次控件 self.ui.widget_unass_fights.setCellWidget(tablerow, 1, combobox1) # 第6、7列下拉框 combobox2 = QComboBox() combobox2.addItem("") combobox3 = QComboBox() combobox3.addItem("") for j in self.pilot_list_combo: combobox2.addItem(j) combobox3.addItem(j) combobox2.setCurrentText(row[6]) combobox3.setCurrentText(row[7]) self.ui.widget_unass_fights.setCellWidget(tablerow, 6, combobox2) self.ui.widget_unass_fights.setCellWidget(tablerow, 7, combobox3) print(self.ui.widget_unass_fights.cellWidget(0, 1).currentText()) def update(self): rowcount = self.ui.widget_unass_fights.rowCount() for i in range(rowcount): flight_id = self.ui.widget_unass_fights.item(i, 0).text() # 增加类型校验避免报错 combo1 = self.ui.widget_unass_fights.cellWidget(i, 1) flight_reg = combo1.currentText() if isinstance(combo1, QComboBox) else "" desc = self.ui.widget_unass_fights.item(i, 2).text() date = self.ui.widget_unass_fights.item(i, 3).text() etd = self.ui.widget_unass_fights.item(i, 4).text() flight_time = self.ui.widget_unass_fights.item(i, 5).text() combo6 = self.ui.widget_unass_fights.cellWidget(i, 6) pilot = combo6.currentText() if isinstance(combo6, QComboBox) else "" combo7 = self.ui.widget_unass_fights.cellWidget(i, 7) co_pilot = combo7.currentText() if isinstance(combo7, QComboBox) else "" max_pax = self.ui.widget_unass_fights.item(i, 8).text()
注:原代码中
def update(self)行缺少冒号,属于语法错误,同步修正。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

