如何从我的 Python 文件更新 Qml 对象的属性?

我想在 Qml 中显示一个矩形,并且我想从我的 Python 代码中更改矩形的属性(宽度、长度)。其实python代码中有一个socket连接,通过这个socket连接从另一台电脑接收width和length的值。简单来说:另一个用户应该能够实时调整这个矩形。我知道如何在我的 python 文件中建立套接字连接并使用 PyQt5,我可以从 python 显示 qml 文件。


但是,我无法通过我的 python 代码访问矩形的参数。我怎样才能做到这一点?


这是我的 qml 文件的简化示例:


import QtQuick 2.11

import QtQuick.Window 2.2

import QtQuick.Controls 2.2


ApplicationWindow {    

    visible: true

    width: Screen.width/2

    height: Screen.height/2

    Rectangle {

        id: rectangle

        x: 187

        y: 92

        width: 200

        height: 200

        color: "blue"

    }

}

这是我在 .py 文件中写的内容:


from PyQt5.QtQml import QQmlApplicationEngine, QQmlProperty

from PyQt5.QtQuick import QQuickWindow, QQuickView

from PyQt5.QtCore import QObject, QUrl

from PyQt5.QtWidgets import QApplication

import sys

def run():

    myApp = QApplication(sys.argv)

    myEngine = QQmlApplicationEngine()


    myEngine.load('mainViewofHoomanApp.qml')



    if not myEngine.rootObjects():

        return -1

    return myApp.exec_()


if __name__ == "__main__":

    sys.exit(run())


紫衣仙女
浏览 175回答 2
2回答

慕尼黑5688855

有几种方法可以从 python/C++ 修改 QML 元素的属性,每种方法都有其优点和缺点。1. 从 QML 中提取引用通过另一个对象通过 findChildren 获取 QML 对象。修改或访问属性与setProperty()或property()分别或QQmlProperty。main.qml(qml用于接下来的 2 .py)import QtQuick 2.11import QtQuick.Window 2.2import QtQuick.Controls 2.2ApplicationWindow {        visible: true    width: Screen.width/2    height: Screen.height/2    Rectangle {        id: rectangle        x: 187        y: 92        width: 200        height: 200        color: "blue"        objectName: "foo_object"    }}1.1 setProperty()、property()。import osimport sysfrom PyQt5 import QtCore, QtGui, QtQmlfrom functools import partialdef testing(r):    import random    w = r.property("width")    h = r.property("height")    print("width: {}, height: {}".format(w, h))    r.setProperty("width", random.randint(100, 400))    r.setProperty("height", random.randint(100, 400))def run():    myApp = QtGui.QGuiApplication(sys.argv)    myEngine = QtQml.QQmlApplicationEngine()    directory = os.path.dirname(os.path.abspath(__file__))    myEngine.load(QtCore.QUrl.fromLocalFile(os.path.join(directory, 'main.qml')))    if not myEngine.rootObjects():        return -1    r = myEngine.rootObjects()[0].findChild(QtCore.QObject, "foo_object")    timer = QtCore.QTimer(interval=500)    timer.timeout.connect(partial(testing, r))    timer.start()    return myApp.exec_()if __name__ == "__main__":    sys.exit(run())1.2 QQml属性。import osimport sysfrom PyQt5 import QtCore, QtGui, QtQmlfrom functools import partialdef testing(r):    import random    w_prop = QtQml.QQmlProperty(r, "width")    h_prop = QtQml.QQmlProperty(r, "height")    print("width: {}, height: {}".format(w_prop.read(), w_prop.read()))    w_prop.write(random.randint(100, 400))    h_prop.write(random.randint(100, 400))def run():    myApp = QtGui.QGuiApplication(sys.argv)    myEngine = QtQml.QQmlApplicationEngine()    directory = os.path.dirname(os.path.abspath(__file__))    myEngine.load(QtCore.QUrl.fromLocalFile(os.path.join(directory, 'main.qml')))    if not myEngine.rootObjects():        return -1    r = myEngine.rootObjects()[0].findChild(QtCore.QObject, "foo_object")    timer = QtCore.QTimer(interval=500)    timer.timeout.connect(partial(testing, r))    timer.start()    return myApp.exec_()if __name__ == "__main__":    sys.exit(run())这种方法的一个缺点是,如果对象与根对象的关系很复杂(有时在其他 QML 中的对象很难用 findChild 访问),访问对象的部分变得复杂,有时甚至不可能,因此该方法将失败。另一个问题是,当使用 objectName 作为主要搜索数据时,Python 层对 QML 层的依赖性很高,因为如果在 QML 中修改了 objectName,则必须修改 Python 中的逻辑。另一个缺点是,通过不管理 QML 对象的生命周期,它可能会在 Python 不知道的情况下被消除,因此它会访问不正确的引用,从而导致应用程序意外终止。2. 推送对 QML 的引用创建一个具有相同类型属性的 QObject。使用 setContextProperty 导出到 QML。在 QObject 的属性和项目的属性之间进行绑定。主文件import QtQuick 2.11import QtQuick.Window 2.2import QtQuick.Controls 2.2ApplicationWindow {        visible: true    width: Screen.width/2    height: Screen.height/2    Rectangle {        id: rectangle        x: 187        y: 92        width: r_manager.width        height: r_manager.height        color: "blue"    }}main.pyimport osimport sysfrom PyQt5 import QtCore, QtGui, QtQmlfrom functools import partialclass RectangleManager(QtCore.QObject):    widthChanged = QtCore.pyqtSignal(float)    heightChanged = QtCore.pyqtSignal(float)    def __init__(self, parent=None):        super(RectangleManager, self).__init__(parent)        self._width = 100        self._height = 100    @QtCore.pyqtProperty(float, notify=widthChanged)    def width(self):        return self._width    @width.setter    def width(self, w):        if self._width != w:            self._width = w            self.widthChanged.emit(w)    @QtCore.pyqtProperty(float, notify=heightChanged)    def height(self):        return self._height    @height.setter    def height(self, h):        if self._height != h:            self._height = h            self.heightChanged.emit(h)def testing(r):    import random    print("width: {}, height: {}".format(r.width, r.height))    r.width = random.randint(100, 400)    r.height = random.randint(100, 400)def run():    myApp = QtGui.QGuiApplication(sys.argv)    myEngine = QtQml.QQmlApplicationEngine()    manager = RectangleManager()    myEngine.rootContext().setContextProperty("r_manager", manager)    directory = os.path.dirname(os.path.abspath(__file__))    myEngine.load(QtCore.QUrl.fromLocalFile(os.path.join(directory, 'main.qml')))    if not myEngine.rootObjects():        return -1    timer = QtCore.QTimer(interval=500)    timer.timeout.connect(partial(testing, manager))    timer.start()    return myApp.exec_()if __name__ == "__main__":    sys.exit(run())缺点是您必须编写更多代码。优点是对象可以被所有 QML 访问,因为它使用了 setContextProperty,另一个优点是如果 QML 对象被删除,它不会产生问题,因为只消除了绑定。最后,通过不使用 objectName,依赖项不存在。所以我更喜欢使用第二种方法,有关更多信息,请阅读Interacting with QML from C++。

富国沪深

尝试以下操作(未测试,但会给您一个想法)。objectname为矩形创建一些,如下所示:Rectangle {        id: rectangle        x: 187        y: 92        width: 200        height: 200        color: "blue"        objectName: "myRect"    }与 QML 交互并找到您的孩子,然后设置属性。    #INTERACT WITH QML    engine = QQmlEngine()    component = QQmlComponent(engine)    component.loadUrl(QUrl('mainViewofHoomanApp.qml'))    object = component.create()    #FIND YOUR RECTANGLE AND SET WIDTH    child = object.findChild(QObject,"myRect")    child.setProperty("width", 500)  
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python