You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将QSqlTableModel的TableView选中行数据填充至QLineEdit并更新模型

Alright, let's tackle this PyQt5 implementation step by step. I'll provide a complete working example and break down the key parts so you can follow along easily.

完整实现代码
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableView, QLineEdit, 
                             QPushButton, QVBoxLayout, QWidget, QHBoxLayout)
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel
from PyQt5.QtCore import Qt

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("SQLite Table Editor")
        self.resize(600, 400)

        # 1. 初始化数据库连接与模型
        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("test.db")
        if not self.db.open():
            print("无法打开数据库")
            return

        # 创建测试表(如果不存在)
        query = self.db.exec_("""
            CREATE TABLE IF NOT EXISTS person (
                name TEXT PRIMARY KEY,
                age INTEGER,
                gender TEXT
            )
        """)
        query.exec_("INSERT OR IGNORE INTO person VALUES ('Alice', 25, 'Female')")
        query.exec_("INSERT OR IGNORE INTO person VALUES ('Bob', 30, 'Male')")
        query.exec_("INSERT OR IGNORE INTO person VALUES ('Charlie', 28, 'Male')")

        # 设置QSqlTableModel
        self.model = QSqlTableModel(self, self.db)
        self.model.setTable("person")
        self.model.select()
        self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)  # 手动提交修改

        # 2. 创建UI组件
        self.table_view = QTableView()
        self.table_view.setModel(self.model)
        self.table_view.setSelectionBehavior(QTableView.SelectRows)  # 整行选中

        # 输入框:name_line设为只读
        self.name_line = QLineEdit()
        self.name_line.setReadOnly(True)
        self.age_line = QLineEdit()
        self.address_line = QLineEdit()  # 按你的命名保留,推测对应gender列

        # 按钮
        self.update_btn = QPushButton("Update")
        self.reset_btn = QPushButton("Reset")  # 加个重置按钮方便测试

        # 布局
        input_layout = QHBoxLayout()
        input_layout.addWidget(self.name_line)
        input_layout.addWidget(self.age_line)
        input_layout.addWidget(self.address_line)

        btn_layout = QHBoxLayout()
        btn_layout.addWidget(self.update_btn)
        btn_layout.addWidget(self.reset_btn)

        main_layout = QVBoxLayout()
        main_layout.addWidget(self.table_view)
        main_layout.addLayout(input_layout)
        main_layout.addLayout(btn_layout)

        central_widget = QWidget()
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)

        # 3. 绑定信号与槽函数
        self.table_view.selectionModel().selectionChanged.connect(self.on_selection_changed)
        self.update_btn.clicked.connect(self.on_update_clicked)
        self.reset_btn.clicked.connect(self.on_reset_clicked)

    def on_selection_changed(self, selected, deselected):
        """选中行变化时,填充输入框"""
        # 获取选中的第一个行索引
        indexes = selected.indexes()
        if indexes:
            row = indexes[0].row()
            # 从模型中获取数据
            name = self.model.data(self.model.index(row, 0), Qt.DisplayRole)
            age = self.model.data(self.model.index(row, 1), Qt.DisplayRole)
            gender = self.model.data(self.model.index(row, 2), Qt.DisplayRole)
            # 填充到输入框
            self.name_line.setText(str(name))
            self.age_line.setText(str(age))
            self.address_line.setText(str(gender))

    def on_update_clicked(self):
        """点击Update按钮,以name为参考更新数据"""
        name = self.name_line.text().strip()
        if not name:
            print("请先选中一行数据")
            return

        # 获取输入的age和gender
        try:
            age = int(self.age_line.text().strip())
        except ValueError:
            print("Age必须是整数")
            return
        gender = self.address_line.text().strip()

        # 找到模型中对应name的行
        match_index = self.model.find(self.model.index(0, 0), name)
        if match_index.isValid():
            # 更新age列(索引1)和gender列(索引2)
            self.model.setData(match_index.siblingAtColumn(1), age)
            self.model.setData(match_index.siblingAtColumn(2), gender)
            # 提交修改到数据库
            if self.model.submitAll():
                print("数据更新成功")
            else:
                print(f"更新失败: {self.model.lastError().text()}")
        else:
            print(f"未找到name为{name}的记录")

    def on_reset_clicked(self):
        """重置输入框与模型"""
        self.name_line.clear()
        self.age_line.clear()
        self.address_line.clear()
        self.model.revertAll()  # 撤销未提交的修改
        self.model.select()  # 重新加载数据

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
关键部分解释

1. 选中行数据填充

我们通过table_view.selectionModel().selectionChanged信号监听选中变化,在on_selection_changed函数中:

  • 获取选中行的索引,从模型中取出对应列的DisplayRole数据
  • 将数据分别设置到三个输入框,注意把整型的age转成字符串适配输入框格式

2. Update按钮的更新逻辑

在on_update_clicked函数中:

  • 先校验输入数据:确保name不为空,age是合法整数
  • 使用model.find()方法快速定位到name匹配的行索引,比遍历所有行更高效
  • 通过setData()更新对应列的数据,然后调用submitAll()提交修改到数据库
  • 如果更新失败,会打印错误信息方便调试问题

3. 额外细节优化

  • 设置model.setEditStrategy(QSqlTableModel.OnManualSubmit),确保修改不会自动提交,必须手动触发submitAll()才会写入数据库,避免误操作
  • 给table_view设置setSelectionBehavior(QTableView.SelectRows),保证整行选中,符合用户常规操作习惯
  • 添加了Reset按钮,方便快速重置输入框和模型状态,恢复初始数据

内容的提问来源于stack exchange,提问作者user3030327

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 19:22:55