如何让PySide6中的QSqlTableModel实现只读切换功能?
问题解决:PySide6中QSqlTableModel表格的只读/编辑状态切换
问题背景
用PySide6开发程序,主窗口可向包含QSqlTableModel的Journal窗口添加笔记,其余功能正常,但无法实现以下效果:
- Journal表格默认处于只读状态
- 点击"只读"复选框后可切换编辑状态
尝试过setEditStrategy和ItemEnabled但未达到预期,需要实现read_only函数的逻辑。
解决方案
要实现该功能,需要结合模型编辑策略和表格交互限制两个层面来控制,同时绑定复选框的状态变化信号到处理函数:
步骤1:绑定复选框信号
在Journal类的__init__方法中,将"只读"复选框的toggled信号绑定到read_only函数(请根据你的UI文件调整复选框的实际对象名,以下假设为read_only_checkbox):
def __init__(self): super(Journal, self).__init__() self.ui = Ui_Journal() self.ui.setupUi(self) Database() self.db = Database() self.view_data() self.ui.update_list_btn.clicked.connect(self.view_data) self.ui.delete_btn.clicked.connect(self.delete_note) # 绑定复选框信号并初始化默认只读状态 self.ui.read_only_checkbox.toggled.connect(self.read_only) self.ui.read_only_checkbox.setChecked(True) self.read_only(True)
步骤2:实现read_only函数逻辑
在read_only函数中,根据复选框状态分别配置模型和表格的编辑权限:
def read_only(self, is_read_only): if not hasattr(self, 'model'): return if is_read_only: # 只读模式:禁止模型自动提交,同时关闭表格所有编辑触发 self.model.setEditStrategy(QSqlTableModel.OnManualSubmit) self.ui.tableView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) else: # 编辑模式:允许字段修改后即时提交,开启双击/回车编辑触发 self.model.setEditStrategy(QSqlTableModel.OnFieldChange) self.ui.tableView.setEditTriggers( QtWidgets.QAbstractItemView.DoubleClicked | QtWidgets.QAbstractItemView.EditKeyPressed )
补充说明
QSqlTableModel.OnManualSubmit:仅手动调用submitAll()才会提交修改,结合表格禁止编辑触发,实现完全只读QSqlTableModel.OnFieldChange:修改字段后立即提交到数据库,适配编辑场景setEditTriggers直接控制用户能否触发表格编辑,是最直观的交互限制方式
修改后的完整Journal类代码
class Journal(QtWidgets.QDialog): def __init__(self): super(Journal, self).__init__() self.ui = Ui_Journal() self.ui.setupUi(self) Database() self.db = Database() self.view_data() self.ui.update_list_btn.clicked.connect(self.view_data) self.ui.delete_btn.clicked.connect(self.delete_note) # 绑定复选框信号并初始化状态 self.ui.read_only_checkbox.toggled.connect(self.read_only) self.ui.read_only_checkbox.setChecked(True) self.read_only(True) def read_only(self, is_read_only): if not hasattr(self, 'model'): return if is_read_only: self.model.setEditStrategy(QSqlTableModel.OnManualSubmit) self.ui.tableView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) else: self.model.setEditStrategy(QSqlTableModel.OnFieldChange) self.ui.tableView.setEditTriggers( QtWidgets.QAbstractItemView.DoubleClicked | QtWidgets.QAbstractItemView.EditKeyPressed ) def view_data(self): header_data = [ '№', 'Имя менеджера', 'Дата запроса', 'Дата обработки', 'Марка машины', 'Модель машины', 'Цвет машины', 'VIN', 'СТС', 'Год выпуска', 'Номер ГН', 'Регион ГН', 'Имя собственника', 'Дата рождения собственника', 'Паспорт собственника', 'ИНН собственника', 'Владеет с', 'По', 'Номер предоставленный собственника', 'Номер установленный собственника', 'Чем вызвана сложность' ] header_ranges = range(21) self.model = QSqlTableModel(self) self.model.setTable('Journal') self.model.select() for x, y in zip(header_data, header_ranges): self.model.setHeaderData(y, QtCore.Qt.Orientation.Horizontal, x) self.ui.tableView.setModel(self.model) self.ui.tableView.resizeColumnsToContents() self.ui.tableView.sortByColumn(0, QtCore.Qt.SortOrder.DescendingOrder) # 刷新模型后重新应用当前只读状态 if self.ui.read_only_checkbox.isChecked(): self.read_only(True) x = self.db.get_amount_note() self.ui.amount_of_notes.setText(str(x)) def delete_note(self): selected = self.ui.tableView.selectedIndexes() rows = set(index.row() for index in selected) rows = list(rows) rows.sort() if not rows: return first = rows[0] self.model.removeRow(first) self.model.select()
内容的提问来源于stack exchange,提问作者GonnaBeDev
相关产品推荐
相关产品推荐

