creinink
creinink

Reputation: 13

Adding text to a QListView window generated

While teaching myself python3 wanting to send data to the terminal using print(message). This was relatively straight forward and i can generate the console list of CAN data (details of code omitted here, just have bare min code) using three lines:

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

Wanting to pretty it all up and start expanding on the data and displaying it, over the last week been learning qt5 designer and pyqt5 and pyuic to generate the GUI for python. So far so good and I can get the thread working to read the CAN port (could have as easily been a UART port for those not familiar with CAN bus) confirmed this with console window still receiving messages, and the GUI window shows up. Then I read a bunch about MVC and watched tutorials and that's were the wheels started to fall off. I cant get in my brain/head around how to load the data into my model to display to the listview window in the GUI. I think i might have the signal and slot correctly done (sure someone will correct me if that isn't the case) but am struggling to get the data in the correct presentation to be displayed from line ??????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()

Upvotes: 1

Views: 1794

Answers (1)

eyllanesc
eyllanesc

Reputation: 243955

First of all do not use str, it is a reserved word in Python and its use is considered bad programming practice.

On the other hand in the case of QListView this is based on the MVC pattern, where the model has the information, the view shows it and the controller handles when and what information is displayed. In this case the model must be a class that inherits from QAbstractListModel, the easiest class to handle is QStandardItemModel, we create an object of that class and we establish it to QListView, after the information is added to the model, the model will internally notify the view causing it to update.

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)  

Upvotes: 1

Related Questions