将文本添加到生成的 QListView window

Adding text to a QListView window generated

自学时 python3 想使用 print(message) 将数据发送到终端。这相对简单,我可以使用三行生成 CAN 数据的控制台列表(这里省略了代码的细节,只有最小代码):

import os #windows os only,
os.system('cls'),
print(myStr) (also not shown here in code, but it does work!)

想要美化这一切并开始扩展数据并显示它,上周一直在学习 qt5 designer 和 pyqt5 以及 pyuic 来为 python 生成 GUI。到目前为止一切顺利,我可以让线程读取 CAN 端口(对于那些不熟悉 CAN 总线的人来说可能很容易成为 UART 端口)通过控制台 window 确认了这一点仍在接收消息,并且 GUI window出现了。然后我阅读了很多关于 MVC 的内容并观看了教程,这就是轮子开始脱落的原因。我无法了解如何将数据加载到我的模型中以显示到 GUI 中的列表视图 window。我想我可能已经正确地完成了信号和插槽(如果不是这样,肯定会有人纠正我)但是我正在努力让数据以正确的方式显示在行 ????? ??self.listView (str)

from PyQt5 import QtCore, QtGui, QtWidgets, QtSvg
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import pyqtSignal

import sys
import can
import threading
import time

class MainWindow(QMainWindow):

    app = None
    Form = None
    receiveUpdateSignal = pyqtSignal(str)

    def __init__(self,app):
        super().__init__()
        self.app = app
        self.initTool()  
        self.initEvent() 

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.listView = QtWidgets.QListView(Form)
        self.listView.setGeometry(QtCore.QRect(40, 40, 256, 192))
        self.listView.setObjectName("listView")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))

    def receiveCan(self):
        while True:
            try:
                message = self.bus.recv(0.2)
                if message is not None:                   
                    print(message)
                    #data = message.data 
                    self.receiveUpdateSignal.emit("messge in")               
            except Exception as e:
                if hasattr(e, 'message'):
                    print(e.message)
                else:
                    print(e)
                break
            time.sleep(0.005)

    def initTool(self):
        self. bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
        return 

    def startReceive(self):
        receiveProcess = threading.Thread(target=self.receiveCan)
        receiveProcess.setDaemon(True)
        receiveProcess.start() 

    def initEvent(self):
        self.receiveUpdateSignal.connect(self.updateReceivedDataDisplay)

    def updateReceivedDataDisplay(self,str):
        if str != "":
            try:
                **??????self.listView (str)**
            except Exception as e:
                if hasattr(e, 'message'):
                    print(e.message)
                else:
                    print(e)
        return        

def main():

    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = MainWindow(app)
    ui.setupUi(Form)
    ui.startReceive()
    Form.show()

    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

首先不要使用str,它是Python中的保留字,使用它被认为是不好的编程习惯。

另一方面,在 QListView 的情况下,这是基于 MVC 模式,其中模型有信息,视图显示它,控制器处理何时显示什么信息。在这种情况下,模型必须是继承自 QAbstractListModel 的 class,最容易处理的 class 是 QStandardItemModel,我们创建一个 class 的对象并将其建立到 QListView,之后信息被添加到模型中,模型将在内部通知视图使其更新。

class MainWindow(QMainWindow):
    ...

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.listView = QtWidgets.QListView(Form)
        self.listView.setGeometry(QtCore.QRect(40, 40, 256, 192))
        self.listView.setObjectName("listView")
        self.model = QtGui.QStandardItemModel()   # <----
        self.listView.setModel(self.model)        # <----

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    ...

    def updateReceivedDataDisplay(self, text):
        if text:
            it = QtGui.QStandardItem(text)
            self.model.appendRow(it)