基于来自 DB (SQLITE) 的 Signal 实时更新 QTableView

Posted

技术标签:

【中文标题】基于来自 DB (SQLITE) 的 Signal 实时更新 QTableView【英文标题】:Live Update QTableView based on Signal from DB (SQLITE) 【发布时间】:2020-05-11 11:51:26 【问题描述】:

我有一个非常基本的 PySide2 程序,它使用 sqlite 的数据集库。

我非常简单的布局文件是

# -*- coding: utf-8 -*-

################################################################################
## Form generated from reading UI file 'basic.ui'
##
## Created by: Qt User Interface Compiler version 5.14.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################

from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
    QObject, QPoint, QRect, QSize, QTime, QUrl, Qt)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
    QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
    QPixmap, QRadialGradient)
from PySide2.QtWidgets import *


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(1034, 803)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.tableWidget = QTableWidget(self.centralwidget)
        if (self.tableWidget.columnCount() < 2):
            self.tableWidget.setColumnCount(2)
        __qtablewidgetitem = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, __qtablewidgetitem)
        __qtablewidgetitem1 = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, __qtablewidgetitem1)
        self.tableWidget.setObjectName(u"tableWidget")
        self.tableWidget.setGeometry(QRect(40, 20, 981, 401))
        self.pushButton = QPushButton(self.centralwidget)
        self.pushButton.setObjectName(u"pushButton")
        self.pushButton.setGeometry(QRect(930, 430, 89, 25))
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)

        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
        ___qtablewidgetitem = self.tableWidget.horizontalHeaderItem(0)
        ___qtablewidgetitem.setText(QCoreApplication.translate("MainWindow", u"Name", None));
        ___qtablewidgetitem1 = self.tableWidget.horizontalHeaderItem(1)
        ___qtablewidgetitem1.setText(QCoreApplication.translate("MainWindow", u"Gender", None));
        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"PushButton", None))
    # retranslateUi


我的主文件是

import os

import dataset
from PySide2 import QtWidgets
from PySide2.QtWidgets import QTableWidgetItem

from layouts.basic import Ui_MainWindow

# delete DB to test
try:
    os.remove("data.db")
except:
    pass


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow) :
    def __init__(self, parent=None) :
        super(MainWindow, self).__init__()

        self.setupUi(self)
        self.showMaximized()

        self.pushButton.pressed.connect(self.upsert)


    def upsert(self):
        db = dataset.connect('sqlite:///data.db')
        table = db['abc']
        for i in range(10):
            table.insert(dict(name='Jane', age=34, gender='female'))

        self.results()

    def results(self) :
        db = dataset.connect('sqlite:///data.db')
        self.tableWidget.setRowCount(0)
        for value in db["abc"] :
            name = value['name']
            gender = value['gender']
            print(gender)

            rowPosition = self.tableWidget.rowCount()
            self.tableWidget.insertRow(rowPosition)
            # self.tableWidget.setSizeAdjustPolicy(
            #     QtWidgets.QAbstractScrollArea.AdjustToContents)
            # self.tableWidget.resizeColumnsToContents()

            self.tableWidget.setItem(rowPosition, 0, QTableWidgetItem(name))
            self.tableWidget.setItem(rowPosition, 1, QTableWidgetItem(gender))


if __name__ == "__main__" :
    app = QtWidgets.QApplication([])
    main_window = MainWindow()
    main_window.show()
    app.exec_()

如您所见,按钮上的主文件创建一个数据库,写入一个名为 abc 的表并插入一些值直到 10 行。完成后,它会调用结果函数并更新表。

现在假设数据已实时写入此数据库,并且每秒不断更新行。

我愿意

    当第一行数据可用时通知结果函数 在数据可用时更新 QtableView,而不是在数据加载完成后更新。

我该怎么做?

【问题讨论】:

【参考方案1】:

这就是我解决它的方法。

我实现了一个非常简单的 QFileSystemWatcher

    w = MainWindow()
    paths = ['data.db']
    fs_watcher = QFileSystemWatcher(paths)
    fs_watcher.fileChanged.connect(w.file_changed)

其中 w 是我的 MainWindow 类。

现在,一旦文件实时更新,QfilesystemWatcher 就会通知 file_changed 类

    def file_changed(self) :
        ---Your Logic Here

这为我解决了。

【讨论】:

以上是关于基于来自 DB (SQLITE) 的 Signal 实时更新 QTableView的主要内容,如果未能解决你的问题,请参考以下文章

Python 连接SQLite数据库文件

来自sqlite的Android中的Textview显示

在同一个db上同时使用基于核心数据和sqlite c的api

基于sqlite3库源码实现增删改查 linux_C语言

带有预加载 sqlite3 数据库的 iOS 单元测试

如何在QTableView Qt C ++中将sqlite db数据显示为多列视图?