【问题标题】:QML slider value using pyqt使用 pyqt 的 QML 滑块值
【发布时间】:2020-06-22 18:09:13
【问题描述】:

我正在尝试制作用于控制伺服的 QML 表单。所以我使用 QT 创建器制作了一个 QML 表单并使用 PYQT 加载它。从 QML 表单中,我试图读取一个滑块值来控制伺服。每次我尝试移动滑块时,它都会显示:

AttributeError: 'NoneType' 对象没有属性 'value' 中止 (核心转储)

这是我的 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
    }

}

任何帮助将不胜感激。 谢谢

【问题讨论】:

    标签: python pyqt qml pyqt5


    【解决方案1】:

    您似乎正在尝试从 python 访问 QML 元素,这被认为是一种不好的做法,所以我不会解释错误的原因在哪里,但我会提出一个更稳定和推荐的解决方案:创建一个 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 属性。

    【讨论】:

      猜你喜欢
      • 2017-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多