QML датчики не обновляются из Python - PullRequest
1 голос
/ 21 октября 2019

Я все еще справляюсь с 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)

receiveata () содержит цикл while с указанными выше деталями, но датчик фактически обновляется только один раз. Если я помещаю инструкцию в файл QML для отображения значения itt1, оно всегда имеет правильное значение, поэтому мне нужно добавить метод, чтобы обнаружить изменение этого значения и перекрасить датчик?

Редактировать: Меня спросили о деталях receiveata (), поэтому я прикрепил его здесь:

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 Ответ

1 голос
/ 21 октября 2019

У вас есть следующие ошибки:

  • Вы не можете напрямую изменять графический интерфейс из другого потока.

  • Значение можно снова экспортировать с помощьюsetContextProperty(), это не изменит предыдущее значение, пока QML не будет перезагружен.

  • Если вы хотите, чтобы "itt" изменил любое значение в QML, оно должно быть совместимого типа, в этомcase значение CircularGauge "real" и, следовательно, тип данных, поддерживаемых в python, является float.

Учитывая вышеизложенное, я создал объект QObject, поскольку он может уведомлять об изменениях с помощью сигналов, так какон поддерживает потоки и экспортирует соединения 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
    }
}
...