Значение слайдера QML с использованием pyqt - PullRequest
1 голос
/ 10 марта 2020

Я пытаюсь создать форму QML для управления сервоприводом. Поэтому я создал QML-форму с использованием создателя QT и загрузил ее с помощью PYQT. Из формы QML я пытаюсь прочитать значение ползунка для управления сервоприводом. Каждый раз, когда я пытаюсь переместить ползунок, он говорит:

AttributeError: у объекта 'NoneType' нет атрибута 'значение' Прервано (сброшено ядро)

Вот мой pyqt код:

import os
import sys
from PyQt5 import QtCore, QtGui, QtQml

dir_path = os.path.dirname(os.path.realpath(__file__))
class MainWindow(QtQml.QQmlApplicationEngine):
    def __init__(self):
        super(QtQml.QQmlApplicationEngine, self).__init__()
        self.load(QtCore.QUrl.fromLocalFile(os.path.join(dir_path, "QML-1.0.qml")))
        self.rootContext().setContextProperty("MainWindow", self)
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.run)
        self.timer.start(10)

        if self.rootObjects():
            # Inherit items from the GUI
            self.window = self.rootObjects()[0]
            self.text = self.window.findChild(QtCore.QObject, "textField")
            self.slider = self.window.findChild(QtCore.QObject, "slider")



    def run(self):
        print (type(self.slider))
    pass


    @QtCore.pyqtProperty(int)
    def rangeValue(self):
        x = self.slider.value()
    print x
        return 10




if __name__ == '__main__':
    app = QtGui.QGuiApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

А вот мой код qml:

import QtQuick 2.0
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
import QtQuick.Controls.Universal 2.0
import QtGraphicalEffects 1.0




ApplicationWindow {
    id: root
    width: 900
    height: 300
    opacity: 1
    title: "window"
    visible: true
    //visibility: Window.FullScreen
    visibility: Window.Maximized

    Dial {
        id: dial
        x: 77
        y: 60
        width: 102
        height: 103
        wheelEnabled: true
    }

    Slider {
        id: slider
        x: 28
        y: 220
        value: 0.5
        onValueChanged: MainWindow.rangeValue(value)
    }

    Label {
        id: label
        x: 64
        y: 16
        width: 128
        height: 24
        text: qsTr("Servo-1")
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
    }

}

Любая помощь будет оценена. Спасибо

1 Ответ

0 голосов
/ 10 марта 2020

Кажется, что вы пытаетесь получить доступ к элементу QML из python, что считается плохой практикой, поэтому я не буду объяснять, где причина ошибки, но я предложу более стабильное и рекомендуемое решение: создайте объект QObject. экспортируйте его в QML и обновите эти свойства из QML до python.

import os
import sys
from PyQt5 import QtCore, QtGui, QtQml

DIR_PATH = os.path.dirname(os.path.realpath(__file__))


class ServoController(QtCore.QObject):
    valueChanged = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(ServoController, self).__init__(parent)
        self._value = 0

        self.valueChanged.connect(self.process_value)

    @QtCore.pyqtProperty(float, notify=valueChanged)
    def value(self):
        return self._value

    @value.setter
    def value(self, v):
        self._value = v
        self.valueChanged.emit()

    def process_value(self):
        print(self.value)


def main():
    app = QtGui.QGuiApplication(sys.argv)

    engine = QtQml.QQmlApplicationEngine()

    servo_controller = ServoController()
    engine.rootContext().setContextProperty("servo_controller", servo_controller)

    url = QtCore.QUrl.fromLocalFile(os.path.join(DIR_PATH, "QML-1.0.qml"))
    engine.load(url)

    def on_object_created(obj, objUrl):
        if obj is None and url == objUrl:
            QtCore.QCoreApplication.exit(-1)

    engine.objectCreated.connect(on_object_created, QtCore.Qt.QueuedConnection)

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
import QtQuick 2.0
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
import QtQuick.Controls.Universal 2.0
import QtGraphicalEffects 1.0


ApplicationWindow {
    id: root
    width: 900
    height: 300
    opacity: 1
    title: "window"
    visible: true
    //visibility: Window.FullScreen
    visibility: Window.Maximized

    Dial {
        id: dial
        x: 77
        y: 60
        width: 102
        height: 103
        wheelEnabled: true
    }

    Slider {
        id: slider
        x: 28
        y: 220
        value: 0.5
        onValueChanged: servo_controller.value = value
        Component.onCompleted: servo_controller.value = value
    }

    Label {
        id: label
        x: 64
        y: 16
        width: 128
        height: 24
        text: qsTr("Servo-1")
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
    }

}

. В предыдущем коде я создал класс ServoController, функция которого заключается в сопоставлении свойств QML с python. например, значение ползунка и вызов функции process_value при изменении этого значения.

В QML я обновляю свойство ServoController при изменении значения ползунка и при запуске.

...