一起使用 psycopg2 和 Qthreads(或者只是 postgresql 和 qthreads)并更新 GUI
Posted
技术标签:
【中文标题】一起使用 psycopg2 和 Qthreads(或者只是 postgresql 和 qthreads)并更新 GUI【英文标题】:Using psycopg2 and Qthreads together(or just postgresql and qthreads) and updating GUI 【发布时间】:2017-12-16 07:18:18 【问题描述】:DB 中的订单簿始终显示正确的订单簿,我只想在 GUI 中不断更新它。我一直试图让它工作,但是当我尝试运行 cur 语句时,应用程序就会崩溃。我怀疑我需要一些帮助才能不必每次都清除表格元素,而只更新已更改的项目(我假设这是一件聪明的事情,但我不确定)。如果我必须使用 Qt 的 postgresql 库,我会,但是你必须帮助我如何让它运行:)
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import pyqtSignal, QThread
import psycopg2
import sys
import time
conn = psycopg2.connect("dbname=myDb user=kris")
cur = conn.cursor()
class Ui_MainWindow(QThread):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(50, 50, 711, 481))
self.tableWidget.setRowCount(3)
self.tableWidget.setColumnCount(4)
self.tableWidget.setHorizontalHeaderLabels(['Sum', 'Total', 'Size', 'Bid'])
self.tableWidget.setObjectName("tableWidget")
self.btnBuy = QtWidgets.QPushButton(self.centralwidget)
self.btnBuy.setGeometry(QtCore.QRect(50, 10, 91, 33))
self.btnBuy.setObjectName("btnBuy")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 29))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.btnBuy.setText(_translate("MainWindow", "BUY"))
class MainUIClass(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__()
self.setupUi(self)
self.threadclass = ThreadClass()
self.threadclass.start()
self.threadclass.updateTable.connect(self.updateTable)
def updateTable(self, val):
print(val)
if 'setRowCount' in val:
self.tableWidget.setRowCount(val['setRowCount'])
elif 'insertRow' in val:
self.tableWidget.insertRow(val['insertRow'])
elif 'setItem' in val:
rowNum = val['setItem'][0]
colNum = val['setItem'][1]
data = val['setItem'][2]
self.tableWidget.setItem(rowNum, colNum+2, QtWidgets.QTableWidgetItem(str(data)))
class ThreadClass(QtCore.QThread):
updateTable = pyqtSignal(dict)
def __init__(self, parent=None):
super().__init__()
def run(self):
cur.execute("select quantity, rate from orderbook where type = %s and market = %s order by rate asc limit 10;", (0, "BTC-ADA"))
orderbook = cur.fetchall()
conn.commit()
for rowNum, rowData in enumerate(orderbook):
self.updateTable.emit("insertRow": 0)
for colNum, data in enumerate(rowData):
self.updateTable.emit("setItem": [rowNum, colNum, data])
if __name__ == "__main__":
a = QtWidgets.QApplication(sys.argv)
app = MainUIClass()
app.show()
#a.exec_()
cur.close()
conn.close()
sys.exit(a.exec_())
【问题讨论】:
【参考方案1】:您在 Qt 的主循环启动之前关闭了数据库连接,将所有与 Postgres 相关的东西移动到线程中。
class ThreadClass(QtCore.QThread):
updateTable = pyqtSignal(dict)
def __init__(self, parent=None):
super().__init__()
def run(self):
conn = psycopg2.connect("dbname=motocompano_dev user=pg_admin password=pGsql_#--w3N_a0X!s7J-o1U+ host=localhost port=5555")
cur = conn.cursor()
cur.execute("select * from events")
orderbook = cur.fetchall()
for rowNum, rowData in enumerate(orderbook):
self.updateTable.emit("insertRow": 0)
for colNum, data in enumerate(rowData):
self.updateTable.emit("setItem": [rowNum, colNum, data])
cur.close()
conn.close()
【讨论】:
啊,这确实有效。在阅读文档后应该尝试过,而不是无休止地寻找“最佳”解决方案......无论如何。这给我留下的只是第 10 行的数据...... 好的!得到那个工作。下一个循环显然使用了“旧”rowNum,因为它在另一个循环内循环。你知道我只能更新新值,还是我应该每次都清空表格并输入新值? 我更喜欢懒惰的方式:清空表格并重新加载所有内容:) 啊。我发现我不必“清除”。我只需要输入新值。我想我仍然可以通过保存初始值并仅在数据更改时调用“发射”来改进它。感谢您的帮助!以上是关于一起使用 psycopg2 和 Qthreads(或者只是 postgresql 和 qthreads)并更新 GUI的主要内容,如果未能解决你的问题,请参考以下文章
如何让 QThreads 在控制台 PySide 程序中工作?