I created a simple listview in qml, and I would like to update its value from a QThread
using QStringListModel
. I have tried several ways, but I could not really get it work. I appriciate all help. I am quite new in Qt
. (Maybe I should pass the self.hosts variable value into another class?)
Here is my python
code:
import os
from pathlib import Path
import sys
import PySide2.QtQml
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QObject, Slot, Signal, Property, QThread, QStringListModel
class Main(QObject):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.worker1 = Worker1()
@Slot()
def startCheck(self):
self.worker1.start()
class Worker1(QThread):
updateListView = Signal(list)
def __init__(self):
QThread.__init__(self)
self.test_model = QStringListModel()
self.updateListView.connect(self.updateModel)
self.hosts = []
def run(self):
#Just keep it simple for test
myList = ["A1", "A2", "A3", "A4", "B1", "B2", "B3"]
for i in myList:
if "A" in i:
self.hosts.append(i)
self.updateListView.emit(self.hosts)
@Slot(list)
def updateModel(self, hosts):
self.test_model.setStringList(hosts)
@Property(QObject, notify=updateListView)
def model(self):
return self.test_model
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
main = Main()
engine.rootContext().setContextProperty("main", main)
worker1 = Worker1()
engine.rootContext().setContextProperty("worker1", worker1)
engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
Here is my qml
code:
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("Update")
anchors.top: parent.top
anchors.topMargin: 21
anchors.horizontalCenterOffset: 0
anchors.horizontalCenter: parent.horizontalCenter
onClicked: main.startCheck()
}
ListView{
id: listView
width: 200
height: 150
anchors.top: parent.top
anchors.topMargin: 55
anchors.horizontalCenter: parent.horizontalCenter
contentWidth: 0
model: worker1.model
delegate: Text { text: display; color: "black" }
}
}
CodePudding user response:
I have figured it out. If anyone knows a better solution, please let me know.
python
code:
import os
from pathlib import Path
import sys
import PySide2.QtQml
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QObject, Slot, Signal, Property, QThread, QStringListModel
class Main(QObject):
getUpdateModel = Signal(list)
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.worker1 = Worker1()
self.worker1.updateListView.connect(self.upDateModel)
self.test_model = QStringListModel()
@Slot()
def startCheck(self):
self.worker1.start()
@Property(QObject, notify=getUpdateModel)
def model(self):
return self.test_model
@Slot(list)
def upDateModel(self, hosts):
self.test_model.setStringList(hosts)
class Worker1(QThread):
updateListView = Signal(list)
def __init__(self):
QThread.__init__(self)
self.hosts = []
def run(self):
#Just keep it simple for test
myList = ["A1", "A2", "A3", "A4", "B1", "B2", "B3"]
for i in myList:
if "A" in i:
self.hosts.append(i)
self.updateListView.emit(self.hosts)
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
main = Main()
engine.rootContext().setContextProperty("main", main)
engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
qml
code:
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("Update")
anchors.top: parent.top
anchors.topMargin: 21
anchors.horizontalCenterOffset: 0
anchors.horizontalCenter: parent.horizontalCenter
onClicked: main.startCheck()
}
ListView{
id: listView
width: 200
height: 150
anchors.top: parent.top
anchors.topMargin: 55
anchors.horizontalCenter: parent.horizontalCenter
contentWidth: 0
model: main.model
delegate: Text { text: display; color: "black" }
}
}