QML量规未从Python更新

时间:2019-10-21 01:40:42

标签: python qml pyside2

我仍在处理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

在线程方法receiveata()中,我从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)

1 个答案:

答案 0 :(得分:1)

您遇到以下错误:

  • 您不能直接从另一个线程修改GUI。

  • 可以使用setContextProperty()再次导出值,除非重新加载QML,否则不会更改以前的值。

  • 如果要“ itt”修改QML中的任何值,它必须是兼容类型,在这种情况下,CircularGauge的值是“ real”,因此python支持的数据类型是float。 p>

考虑到上述情况,我创建了一个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
    }
}