Python列表更新时更新ListView

时间:2019-07-02 19:57:35

标签: python qml pyside2

我正在尝试使用PySide根据来自csv文件的数据更新QML中的ListView。该csv文件是由外部程序更新的,因此我设置了一个循环,以循环方式从该文件中获取数据。

我能够将数据导入Python并打印出来,但是我认为我的错误是信号/插槽问题,并且根本没有在QML中更新。

main.py:

def importSimStatus(statusOutput):
    with open(r'status output.csv','r') as readFile:

        dummyList2 = statusOutput.outputStatus

        i = 0

        for j in range(8):
            statusOutput.setOutputStatus("", j)

        csvReader = csv.reader(readFile)
        for row in csvReader:


            statusOutput.setOutputStatus(row[0], i)
            dummyList2 = statusOutput.outputStatus

            i += 1


def checkSimOutput():

    for out in range(8):
        statusOutput.setOutputStatus("", out)

    simResults = []

    dummyList = statusOutput.outputStatus
    while (dummyList[7] == ""):
        try:
            importSimStatus(statusOutput)


        except:
            pass
        time.sleep(1)

        print(statusOutput.outputStatus)

class CheckSimOutput(QRunnable):
    def run(self):
        checkSimOutput()


class OutputData(QObject):

    statusSig = Signal(list)


    def __init__(self, parent=None):
        QObject.__init__(self, parent)
        self.m_outputStatus = []        

    def resizeOutputStatus(self, i):
        for x in range(i):
            self.m_outputStatus.append("")

    @Property(list, notify=statusSig)
    def outputStatus(self):
        return self.m_outputStatus

    @outputStatus.setter
    def setOutputStatus(self, text, i):
        if self.m_outputStatus[i] == text:
            return
        self.m_outputStatus[i] = text
        self.statusSig.emit(self.m_outputStatus)

class Settings(QObject):


    simWorkAround = Signal(int)

    def __init__(self, parent=None):
        QObject.__init__(self, parent)

        self.m_simWorkAround = 0

    @Property(int, notify=simWorkAround)
    def simWorkaround(self):
        return self.m_simWorkAround

    @simWorkaround.setter
    def setSimWorkaround(self, num):
        if self.m_simWorkAround == num:
            return
        self.m_simWorkAround = num
        self.simWorkAround.emit(self.m_simWorkAround)

if __name__ == '__main__':

    app = QGuiApplication(sys.argv)

    settings = Settings()
    statusOutput = OutputData()

    statusOutput.resizeOutputStatus(8)

    def simThread():
        simOutRunnable = CheckSimOutput()
        QThreadPool.globalInstance().start(simOutRunnable)


    model = QStringListModel()
    model.setStringList(statusOutput.outputStatus)

    engine = QQmlApplicationEngine()

    engine.rootContext().setContextProperty("settings", settings)
    engine.rootContext().setContextProperty("myModel", model)

    engine.load(QUrl.fromLocalFile('mainfile.qml'))
    if not engine.rootObjects():
        sys.exit(-1)

    settings.simWorkAround.connect(simThread)
    statusOutput.statusSig.connect(model.setStringList(statusOutput.outputStatus))


    sys.exit(app.exec_())

mainfile.qml:

import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.1


ApplicationWindow {

visible: true
width: 640
height: 480
title: qsTr("Main Program")

       Button {
           text: qsTr("Start Draft")
           anchors.top: parent.top
           anchors.topMargin: 21
           anchors.horizontalCenterOffset: 0
           anchors.horizontalCenter: parent.horizontalCenter
           onClicked: settings.simWorkaround = settings.simWorkaround + 1
       }



        ListView{
            id: listView
            x: 0
            width: 200
            height: 150
            anchors.top: parent.top
            anchors.topMargin: 55
            anchors.horizontalCenter: parent.horizontalCenter
            contentWidth: 0
            model: myModel
                //anchors.fill: parent
            delegate: Text { text: model.display }
        }


    }

如上所述,从csv文件导入后,我可以获取要打印的列表。我还可以通过添加以下项目来“预加载”列表:

statusOutput.setOutputStatus("foo",0)
statusOutput.setOutputStatus("bar",1)

在“ engine.rootContext()。setContextProperty(” myModel“,model)”之前,我可以看到“ foo”和“ bar”的列表,但是单击我的按钮运行循环时什么也没有发生

如何在statusOutput更新时刷新ListView?

1 个答案:

答案 0 :(得分:1)

您正在组合许多破坏Single responsibility principle的元素,这些元素表明每个类必须具有定义的功能。

在这种情况下,我只创建了2个类:

  • FileWorker是一个驻留在另一个线程中的QObject,它读取文件并发出带有信息的信号。

  • FileManager是一个暴露于QML的QObject,具有作为属性的模型,还具有一个允许重新加载数据的插槽。

main.py:

import os
import csv
from functools import partial
from PySide2 import QtCore, QtGui, QtQml

CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))


class FileWorker(QtCore.QObject):
    linesChanged = QtCore.Signal(list)

    @QtCore.Slot(str)
    def read_csv(self, filename):
        lines = []
        with open(filename, "r") as f:
            csv_reader = csv.reader(f)
            for i, row in enumerate(csv_reader):
                if i > 7:
                    break
                lines.append(row[0])
        self.linesChanged.emit(lines)


class FileManager(QtCore.QObject):
    def __init__(self, parent=None):
        super(FileManager, self).__init__(parent)
        self.m_model = QtCore.QStringListModel(self)
        self.m_thread = QtCore.QThread(self)
        self.m_thread.start()
        self.m_worker = FileWorker()
        self.m_worker.moveToThread(self.m_thread)
        self.m_worker.linesChanged.connect(self.updateModel)

    @QtCore.Property(QtCore.QAbstractItemModel, constant=True)
    def model(self):
        return self.m_model

    @QtCore.Slot()
    def load(self):
        filename = os.path.join(CURRENT_DIR, "status output.csv")
        wrapper = partial(self.m_worker.read_csv, filename)
        QtCore.QTimer.singleShot(0, wrapper)

    def clean(self):
        self.m_thread.quit()
        self.m_thread.wait()

    @QtCore.Slot(list)
    def updateModel(self, lines):
        self.m_model.setStringList(lines)


if __name__ == "__main__":
    import sys

    app = QtGui.QGuiApplication(sys.argv)

    engine = QtQml.QQmlApplicationEngine()

    filemanager = FileManager()
    filemanager.load()

    engine.rootContext().setContextProperty("filemanager", filemanager)
    filename = os.path.join(CURRENT_DIR, "mainfile.qml")
    engine.load(QtCore.QUrl.fromLocalFile(filename))
    if not engine.rootObjects():
        sys.exit(-1)

    res = app.exec_()

    filemanager.clean()

    sys.exit(res)

mainfile.qml:

import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Window 2.2


ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Main Program")

    Button {
        text: qsTr("Start Draft")
        anchors.top: parent.top
        anchors.topMargin: 21
        anchors.horizontalCenterOffset: 0
        anchors.horizontalCenter: parent.horizontalCenter
        onClicked: filemanager.load()
    }

    ListView{
        id: listView
        width: 200
        height: 150
        anchors.top: parent.top
        anchors.topMargin: 55
        anchors.horizontalCenter: parent.horizontalCenter
        contentWidth: 0
        model: filemanager.model
        // anchors.fill: parent
        delegate: Text { text: model.display }
    }
}