QML 仪表未从 Python 更新
QML gauges not updating from Python
我还在努力掌握 QT...我制作了一个 python 文件和一个 QML 文件。 Python 文件根据通过 UDP 获取的数据更新仪表值。
虽然这只有效一次...第一个 UDP 数据包进入并更新仪表,但是当它收到下一个数据包时,尽管值更新,仪表本身却没有。
QML
CircularGauge {
id: circularGauge
x: 30
y: 30
value: itt1value
minimumValue: 0
maximumValue: 1200
tickmarksVisible: false
style: CircularGaugeStyle {
maximumValueAngle: 400
minimumValueAngle: 90
}
}
Python:
def configureApplication():
# Set up the application window
app = QGuiApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
view.setTitle("my title")
# Load the QML file
qml_file = os.path.join(os.path.dirname(__file__), "maingui.qml")
view.setSource(QUrl.fromLocalFile(os.path.abspath(qml_file)))
# load the slots into the QML file
view.rootContext().setContextProperty("itt1value", 0)
t = threading.Thread(target=receivedata, args=(view,))
t.start()
# Show the window
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
# execute and cleanup
app.exec_()
del view
在线程方法 receivedata() 中,我从 UDP 获取数据,处理它,然后像这样将它发送到仪表:
view.rootContext().setContextProperty("itt1value", itt)
receivedata() 中有一个包含上述详细信息的 while 循环,但仪表实际上只更新一次。如果我在 QML 文件中放置一个语句来显示 itt1value,它总是有正确的值,那么我是否需要放置一个方法来检测这个值的变化并重新绘制仪表?
编辑:有人问我 receivedata() 的细节,所以我把它附在这里:
def receivedata(view):
print("Starting UDP server...")
UDP_IP = "192.168.0.14"
UDP_PORT = 49000
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
olditt = 0
loopruns = 0 # for debugging
while True:
rawstring = sock.recv(1024)
hexarray = []
#lots of irrelevent formatting here, result is int(value)
itt = float(hextoint(value, olditt))
olditt = itt
itt = format(itt, '.3f')
current = str(loopruns) # for debugging
view.setTitle(current) # for debugging
view.rootContext().setContextProperty("itt1value", itt)
loopruns = loopruns + 1
print(itt)
您有以下错误:
您不能直接从另一个线程修改 GUI。
可以使用setContextProperty()
再次导出值,除非重新加载QML,否则不会更改以前的值。
如果你想"itt"修改QML中的任何值,它必须是兼容类型,在这种情况下,CircularGauge的值是"real",因此数据类型python 支持的是 float。
考虑到以上情况,我创建了一个 QObject,因为它是线程安全的,可以通过信号通知更改,并导出使用 Connections 建立连接的 QObject。
main.py
import os
import random
import sys
import threading
import time
from PySide2.QtCore import QObject, QUrl, Signal
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
class Connections(QObject):
titleChanged = Signal(str, arguments=["title"])
valueChanged = Signal(float, arguments=["value"])
def receivedata(connector):
# configurations
loopruns = 0
while True:
# other stuff
time.sleep(0.1)
itt = random.uniform(0.0, 1200.0)
connector.valueChanged.emit(itt)
connector.titleChanged.emit(str(loopruns))
loopruns += 1
def main(args):
app = QGuiApplication(args)
view = QQuickView(title="my title", resizeMode=QQuickView.SizeRootObjectToView)
connector = Connections()
connector.titleChanged.connect(view.setTitle)
view.rootContext().setContextProperty("connector", connector)
# Load the QML file
qml_file = os.path.join(os.path.dirname(__file__), "maingui.qml")
view.setSource(QUrl.fromLocalFile(os.path.abspath(qml_file)))
# start thread
threading.Thread(target=receivedata, args=(connector,)).start()
# Show the window
if view.status() == QQuickView.Error:
return -1
view.show()
# execute and cleanup
ret = app.exec_()
del view
return ret
if __name__ == "__main__":
sys.exit(main(sys.argv))
maingui.qml
import QtQml 2.13
import QtQuick.Extras 1.4
import QtQuick.Controls.Styles 1.4
CircularGauge {
id: circularGauge
value: 100
minimumValue: 0
maximumValue: 1200
tickmarksVisible: false
style: CircularGaugeStyle {
maximumValueAngle: 400
minimumValueAngle: 90
}
Connections{
target: connector
onValueChanged: circularGauge.value = value
}
}
我还在努力掌握 QT...我制作了一个 python 文件和一个 QML 文件。 Python 文件根据通过 UDP 获取的数据更新仪表值。
虽然这只有效一次...第一个 UDP 数据包进入并更新仪表,但是当它收到下一个数据包时,尽管值更新,仪表本身却没有。
QML
CircularGauge {
id: circularGauge
x: 30
y: 30
value: itt1value
minimumValue: 0
maximumValue: 1200
tickmarksVisible: false
style: CircularGaugeStyle {
maximumValueAngle: 400
minimumValueAngle: 90
}
}
Python:
def configureApplication():
# Set up the application window
app = QGuiApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
view.setTitle("my title")
# Load the QML file
qml_file = os.path.join(os.path.dirname(__file__), "maingui.qml")
view.setSource(QUrl.fromLocalFile(os.path.abspath(qml_file)))
# load the slots into the QML file
view.rootContext().setContextProperty("itt1value", 0)
t = threading.Thread(target=receivedata, args=(view,))
t.start()
# Show the window
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
# execute and cleanup
app.exec_()
del view
在线程方法 receivedata() 中,我从 UDP 获取数据,处理它,然后像这样将它发送到仪表:
view.rootContext().setContextProperty("itt1value", itt)
receivedata() 中有一个包含上述详细信息的 while 循环,但仪表实际上只更新一次。如果我在 QML 文件中放置一个语句来显示 itt1value,它总是有正确的值,那么我是否需要放置一个方法来检测这个值的变化并重新绘制仪表?
编辑:有人问我 receivedata() 的细节,所以我把它附在这里:
def receivedata(view):
print("Starting UDP server...")
UDP_IP = "192.168.0.14"
UDP_PORT = 49000
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
olditt = 0
loopruns = 0 # for debugging
while True:
rawstring = sock.recv(1024)
hexarray = []
#lots of irrelevent formatting here, result is int(value)
itt = float(hextoint(value, olditt))
olditt = itt
itt = format(itt, '.3f')
current = str(loopruns) # for debugging
view.setTitle(current) # for debugging
view.rootContext().setContextProperty("itt1value", itt)
loopruns = loopruns + 1
print(itt)
您有以下错误:
您不能直接从另一个线程修改 GUI。
可以使用
setContextProperty()
再次导出值,除非重新加载QML,否则不会更改以前的值。如果你想"itt"修改QML中的任何值,它必须是兼容类型,在这种情况下,CircularGauge的值是"real",因此数据类型python 支持的是 float。
考虑到以上情况,我创建了一个 QObject,因为它是线程安全的,可以通过信号通知更改,并导出使用 Connections 建立连接的 QObject。
main.py
import os
import random
import sys
import threading
import time
from PySide2.QtCore import QObject, QUrl, Signal
from PySide2.QtGui import QGuiApplication
from PySide2.QtQuick import QQuickView
class Connections(QObject):
titleChanged = Signal(str, arguments=["title"])
valueChanged = Signal(float, arguments=["value"])
def receivedata(connector):
# configurations
loopruns = 0
while True:
# other stuff
time.sleep(0.1)
itt = random.uniform(0.0, 1200.0)
connector.valueChanged.emit(itt)
connector.titleChanged.emit(str(loopruns))
loopruns += 1
def main(args):
app = QGuiApplication(args)
view = QQuickView(title="my title", resizeMode=QQuickView.SizeRootObjectToView)
connector = Connections()
connector.titleChanged.connect(view.setTitle)
view.rootContext().setContextProperty("connector", connector)
# Load the QML file
qml_file = os.path.join(os.path.dirname(__file__), "maingui.qml")
view.setSource(QUrl.fromLocalFile(os.path.abspath(qml_file)))
# start thread
threading.Thread(target=receivedata, args=(connector,)).start()
# Show the window
if view.status() == QQuickView.Error:
return -1
view.show()
# execute and cleanup
ret = app.exec_()
del view
return ret
if __name__ == "__main__":
sys.exit(main(sys.argv))
maingui.qml
import QtQml 2.13
import QtQuick.Extras 1.4
import QtQuick.Controls.Styles 1.4
CircularGauge {
id: circularGauge
value: 100
minimumValue: 0
maximumValue: 1200
tickmarksVisible: false
style: CircularGaugeStyle {
maximumValueAngle: 400
minimumValueAngle: 90
}
Connections{
target: connector
onValueChanged: circularGauge.value = value
}
}