PyQt 中 QTableView 在更换数据库后无法填充数据问题的解决方法

87 阅读1分钟

在 PyQt 中,我尝试允许用户选择要打开的数据库,每个数据库都有相同的模式。然而,在打开数据库后,我无法让 QTableView 填充数据。

下面是代码示例:

class aMainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.db = QSqlDatabase.addDatabase("QSQLITE")

        self.db.setDatabaseName('testdb.db')
        self.db.open()   

        # Set up the user interface from Designer.
        self.setupUi(self)

        #self.db.setDatabaseName('testdb.db')

        self.model = QSqlTableModel(self)
        self.model.setTable("records")

        self.model.setSort(FILEORDER, Qt.AscendingOrder)

        self.model.setHeaderData(ID, Qt.Horizontal, QVariant("ID"))
        self.model.setHeaderData(FILEORDER, Qt.Horizontal, QVariant("File Order"))
        self.model.setHeaderData(RECORDTYPE, Qt.Horizontal, QVariant("Type"))
        self.model.setHeaderData(NAME, Qt.Horizontal, QVariant("Name"))
        self.model.setHeaderData(PRESORTNAME, Qt.Horizontal, QVariant("Presort Name"))
        self.model.setHeaderData(RECORD, Qt.Horizontal, QVariant("Record"))
        self.model.select()

        self.tableView.setModel(self.model)
        #self.view.setSelectionMode(QTableView.SingleSelection)
        #self.view.setSelectionBehavior(QTableView.SelectRows)
        self.tableView.setColumnHidden(ID, True)
        self.tableView.setColumnHidden(PRESORTNAME, True)
        self.tableView.setColumnHidden(RECORD, True)

当数据库名称为 testdb.db 时,代码可以正常工作,但如果通过文件选择对话框选择其他数据库,则 QTableView 无法填充数据。

2、解决方案

根据一个论坛帖子的提示,发现连接必须在创建模型之前进行,因为模型构造中可能会接触到数据库。因此,将 on_actionOpen_DB_triggered 函数修改为在创建连接后创建模型,即可解决问题。

修改后的代码示例:

class aMainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        # Set up the user interface from Designer.
        self.setupUi(self)

        #self.db.setDatabaseName('testdb.db')

        self.model = QSqlTableModel(self)
        self.model.setTable("records")

        self.model.setSort(FILEORDER, Qt.AscendingOrder)

        self.model.setHeaderData(ID, Qt.Horizontal, QVariant("ID"))
        self.model.setHeaderData(FILEORDER, Qt.Horizontal, QVariant("File Order"))
        self.model.setHeaderData(RECORDTYPE, Qt.Horizontal, QVariant("Type"))
        self.model.setHeaderData(NAME, Qt.Horizontal, QVariant("Name"))
        self.model.setHeaderData(PRESORTNAME, Qt.Horizontal, QVariant("Presort Name"))
        self.model.setHeaderData(RECORD, Qt.Horizontal, QVariant("Record"))
        self.model.select()

        self.tableView.setModel(self.model)
        #self.view.setSelectionMode(QTableView.SingleSelection)
        #self.view.setSelectionBehavior(QTableView.SelectRows)
        self.tableView.setColumnHidden(ID, True)
        self.tableView.setColumnHidden(PRESORTNAME, True)
        self.tableView.setColumnHidden(RECORD, True)


    #slot of the open db action
    def on_actionOpen_DB_triggered(self, checked=None):
        if checked is None: return
        filename = QFileDialog.getOpenFileName(self, 'open a database',
                        '/home/',
                        "Databases (*.db)", #All Files (*.*)
                        "Databases (*.db)")
        if not filename:
            pass

        self.db = QSqlDatabase.addDatabase("QSQLITE")

        if self.db.isOpen():
            sys.stdout.write('db still open?')

        self.db.setDatabaseName(filename)
        self.dbname = filename
        self.db.open()
        self.model.select() # 将模型的 select() 方法移到此处
        #self.tableView.update()
        if self.db.isOpen():
            sys.stdout.write('db opened')

通过这种方式,可以在更换数据库后成功填充 QTableView 的数据。