我正在尝试使用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?
答案 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 }
}
}