Добавление текста в созданное окно QListView

Учусь 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, pyqt5 и pyuic для создания графического интерфейса для python. Пока все хорошо, и я могу заставить поток работать для чтения порта CAN (с тем же успехом это мог быть порт UART для тех, кто не знаком с шиной CAN), подтвердил это, когда окно консоли все еще получает сообщения, и появляется окно графического интерфейса. Потом я много читал про MVC и смотрел туториалы, и тут-то колеса и начали отваливаться. Я не могу понять, как загрузить данные в мою модель для отображения в окне списка в графическом интерфейсе. Я думаю, что у меня могут быть правильно настроены сигнал и слот (конечно, кто-то поправит меня, если это не так), но я изо всех сил пытаюсь получить данные в правильном представлении, которые будут отображаться из строки ?????? self.listView (ул)

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()

person creinink    schedule 08.06.2018    source источник


Ответы (1)


Прежде всего, не используйте str, это зарезервированное слово в Python, и его использование считается плохой практикой программирования.

С другой стороны, в случае QListView это основано на MVC, где модель имеет информацию, представление показывает ее, а контроллер обрабатывает, когда и какая информация отображается. В этом случае модель должна быть классом, наследуемым от QAbstractListModel, самый простой для обработки класс — это QStandardItemModel, мы создаем объект этого класса и устанавливаем его в 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)  
person eyllanesc    schedule 08.06.2018
comment
Спасибо, Эйланеск. Я добавил эти четыре строки, и это просто сработало. Наряду с комментарием @Blinxen удалось увидеть, как StandartItemModel в этом случае немного проще с appendRow() и не нужно беспокоиться о beginInsertRow(). Btw никогда бы сознательно не использовал зарезервированные слова для переменных (исходя из встроенного мира C)! По мере того, как я лучше знакомлюсь с языком, я буду избегать таких ошибок. - person creinink; 11.06.2018