PyQt6 QTableView实现商品选择与UOM自动填充功能求助
问题解决思路与代码修正
一、明确:QTableView完全适配你的需求
QTableView是Qt官方用于表格数据展示、编辑的标准组件,配合自定义AbstractTableModel能灵活控制数据逻辑,完全满足你订单展示、商品选择联动UOM的需求,不用换组件。
二、先修复你的TableViewModel代码
原代码有几个致命问题导致无法运行,修正后的版本如下:
from PyQt6 import QtCore, QtGui, QtWidgets class TableViewModel(QtCore.QAbstractTableModel): def __init__(self, data): super().__init__() # data建议用二维列表结构,比如[[1, "", "", 0, 0], [2, "", "", 0, 0]] self._data = data self.header = ["No.", "Products", "UOM", "Ordered", "Supplied"] def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role: int = QtCore.Qt.ItemDataRole.DisplayRole): if orientation == QtCore.Qt.Orientation.Horizontal and role == QtCore.Qt.ItemDataRole.DisplayRole: if section < len(self.header): return self.header[section] # 其他情况返回默认值 return super().headerData(section, orientation, role) def data(self, index: QtCore.QModelIndex, role: int = QtCore.Qt.ItemDataRole.DisplayRole): if not index.isValid(): return None row = index.row() col = index.column() if role == QtCore.Qt.ItemDataRole.DisplayRole or role == QtCore.Qt.ItemDataRole.EditRole: # 返回对应单元格的数据,UOM列留空后续填充 return self._data[row][col] return super().data(index, role) def rowCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()): # 父索引无效时返回数据行数,表格模型标准写法 if parent.isValid(): return 0 return len(self._data) def columnCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()): if parent.isValid(): return 0 # 用表头长度更灵活,避免硬编码 return len(self.header) def setData(self, index: QtCore.QModelIndex, value, role: int = QtCore.Qt.ItemDataRole.EditRole): if not index.isValid() or role != QtCore.Qt.ItemDataRole.EditRole: return False row = index.row() col = index.column() self._data[row][col] = value # 必须发信号通知视图更新,否则修改后界面不刷新 self.dataChanged.emit(index, index) return True def flags(self, index: QtCore.QModelIndex): if not index.isValid(): return QtCore.Qt.ItemFlag.NoItemFlags return QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsEditable
三、实现点击商品列弹出对话框+联动UOM
1. 写商品选择对话框(含数据库加载逻辑)
这里用模拟数据演示,你替换成实际数据库查询代码即可:
class ProductSelectDialog(QtWidgets.QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("选择商品") self.resize(400, 300) layout = QtWidgets.QVBoxLayout(self) # 商品列表视图 self.table_view = QtWidgets.QTableView() # 替换成你的数据库查询结果:商品ID、名称、UOM self.product_data = [ [1, "苹果", "箱"], [2, "香蕉", "串"], [3, "橙子", "袋"] ] # 用QStandardItemModel快速展示,也可以用自定义模型 self.product_model = QtGui.QStandardItemModel() self.product_model.setHorizontalHeaderLabels(["ID", "商品名称", "包装单位"]) for row in self.product_data: items = [QtGui.QStandardItem(str(item)) for item in row] self.product_model.appendRow(items) self.table_view.setModel(self.product_model) self.table_view.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) # 确认按钮 self.confirm_btn = QtWidgets.QPushButton("确认选择") self.confirm_btn.clicked.connect(self.accept) layout.addWidget(self.table_view) layout.addWidget(self.confirm_btn) # 获取选中的商品信息 def get_selected_product(self): selected_rows = self.table_view.selectionModel().selectedRows() if not selected_rows: return None row = selected_rows[0].row() return (self.product_data[row][1], self.product_data[row][2])
2. 主窗口绑定点击事件,实现联动
class MainWindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("客户订单管理") self.resize(800, 400) # 初始化模拟订单数据 self.order_data = [ [1, "", "", 0, 0], [2, "", "", 0, 0], [3, "", "", 0, 0] ] # 创建模型和视图 self.table_model = TableViewModel(self.order_data) self.table_view = QtWidgets.QTableView() self.table_view.setModel(self.table_model) # 绑定点击事件 self.table_view.clicked.connect(self.on_table_clicked) self.setCentralWidget(self.table_view) def on_table_clicked(self, index): # 只处理商品列(索引1)的点击 if index.column() == 1: dialog = ProductSelectDialog(self) if dialog.exec() == QtWidgets.QDialog.DialogCode.Accepted: product_info = dialog.get_selected_product() if product_info: product_name, uom = product_info # 更新商品列 self.table_model.setData(self.table_model.index(index.row(), 1), product_name) # 自动填充UOM列 self.table_model.setData(self.table_model.index(index.row(), 2), uom)
3. 运行主程序
if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec())
四、补充说明
- 数据库部分:在
ProductSelectDialog的__init__里,把模拟的product_data替换成你的数据库查询逻辑(比如用sqlite3、SQLAlchemy等) - 添加新行:如果需要动态加订单行,可以给主窗口加按钮,调用模型的
beginInsertRows和endInsertRows方法添加空行 - 数据保存:修改订单数据后,把
self.order_data写入数据库即可完成持久化
内容的提问来源于stack exchange,提问作者wondergod
相关产品推荐
相关产品推荐

