当前位置: 首页 > 面试题库 >

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

朱宜
2023-03-14
问题内容

我想在Qml中显示一个矩形,并且想从我的python代码中更改矩形的属性(宽度,长度)。实际上,在python代码中有一个套接字连接,通过该套接字连接可以从另一台计算机接收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())

问题答案:

有几种方法可以从python / C ++修改QML元素的属性,每种方法都有其优点和缺点。

  • 通过findChildren通过另一个对象获取QML对象。
  • 修改或访问属性与setProperty()property()分别或QQmlProperty。

main.qmlqml 用于接下来的2个.py)

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"
        objectName: "foo_object"
    }
}

1.1 setProperty(),property()。

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

def 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 QQmlProperty。

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

def 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的属性和项目的属性之间进行绑定。

main.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: r_manager.width
        height: r_manager.height
        color: "blue"
    }
}

main.py

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

class 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())

缺点是您必须编写更多代码。优点是,由于该对象使用setContextProperty,因此所有QML都可以访问该对象;另一个优点是,如果删除了QML对象,则不会产生问题,因为仅消除了绑定。最后,通过不使用objectName,依赖项不存在。

因此,我更喜欢使用第二种方法,有关更多信息,请阅读C ++中的与QML交互。



 类似资料:
  • 问题内容: 我有一个像这样的JSON字符串: 我想将属性更新为,如果值为,并且值为。 我已经到了这一点,但是不确定如何进行: 我不知道怎么去的是一个孩子。 提前致谢。任何指针都很棒。 问题答案: 您可以使用属性作为键来访问对象: 对于您的示例,请尝试:

  • 我有一个充满行的文件,其中每一行都有银行账户对象的属性。文件布局示例: 1, IE33483, alex,1,100,20, s 2,IE30983,乔,1,0,20,c 3,IE67983,汤姆,1,70,20,s 我试图创建一些代码,将搜索这个文件的用户输入(例如,他们输入他们的id,这是每行的第一个元素),并将使用这3个属性来创建一个对象。有什么帮助吗?这是我到目前为止所尝试的,但它似乎不适

  • 问题内容: 我有一个具有多个相关属性的类,例如: 如果我正常地制作一个对象,那没有问题, 我将得到2个列表,和。 现在,如果我想先创建一个空对象,并为其分配一个属性,则希望其他属性自动更新,例如 我想自动更新,也想自动更新(分配和自动更新)。这可能吗? Class 是否是正确的选择? 谢谢大家,但是所有其他答案让我完全不知所措。谁能提供一个完整的解决方案,让我可以学习编写自己的解决方案? 我想实现

  • 假设我们有以下集合,我对此没有什么问题: > 我想增加“item_name”的价格:“my_item_two”,如果它不存在,应该将它追加到“items”数组中。

  • 我尝试了以下方法,但在编辑归档后,它会更改样式,但也会更改列表中其他ListCell的样式。

  • 问题内容: 我需要从URL对象创建一个File对象我的需求是我需要创建一个网络图像的文件对象(例如googles徽标) 问题答案: 您可以利用以便从URL加载图像,然后将其写入文件。像这样: 如果需要,这还允许您将图像转换为其他格式。