将属性注入 QML 组件
Injecting Properties into QML-Component
我是 Qt/PyQt 的新手,目前正在努力使用一些基本功能。我想做的是,从 python 动态加载 QML-Views (*.qml) 文件并即时替换特定内容。例如,一个复选框被选中,我当前视图的一部分被另一个 qml 文件替换。首先我想通过 PyQt 提供这个逻辑,但似乎 StackView 是一个更好的主意 (multiple qml files in pyqt)。
但是,在这种情况下,我无法将属性注入到我的 QML 文件中。我只能将 属性 注入 rootContext。然而,这限制了我的 QML-Views 的使用,因为我一次只能使用一个视图(相同类型)。我想将属性动态注入 QML-Views 并使它们仅对该特定视图可见。在这种情况下,我可以在后端使用多个对象多次使用相同的视图来捕获信号。
这是我的 SimpleMainWindow.qml 文件(主视图:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Controls 1.4
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
objectName : "WINDOW"
property ApplicationWindow appWindow : window
}
这里是我尝试加载的文件 (TestViewButton.qml):
import QtQuick 2.9
import QtQuick.Controls 1.4
Button {
id: test
text: "test"
objectName : "Button"
onClicked: {
configurator.sum(1, 2)
configurator.info("TestOutput")
}
}
Python 文件加载 QML-View(组件)
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine, QQmlComponent
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load("qml/SimpleMainWindow.qml")
engine.quit.connect(app.quit)
rootWindow = engine.rootObjects()[0].children()[0].parent()
# create component
component = QQmlComponent(engine)
component.loadUrl(QUrl("qml/TestViewButton.qml"))
configurator = SignalHandler()
component.setProperty("configurator", configurator)
itm = component.create()
itm.setParentItem(rootWindow.children()[0])
itm.setProperty("configurator", configurator)
app.exec_()
以及我用来处理来自视图 (SignalHandler.py) 的信号的 python 对象:
from PyQt5.QtCore import QObject, pyqtSlot
class SignalHandler(QObject):
@pyqtSlot(int, int)
def sum(self, arg1, arg2):
print("Adding two numbers")
@pyqtSlot(str)
def info(self, arg1):
print("STR " + arg1)
按钮加载正常(顺便说一句,有没有更好的方法来识别我想添加我的按钮的父级,没有用 findChild 查看)。 component.setProperty..... 部分不起作用。如果我在引擎的 rootContext 中设置 属性 它工作正常(调用 SignalHandler 方法)。已经检查过类似的主题(例如 ...)
这可能吗,还是我这里有问题?
谢谢
据我了解,您只想在 TestViewButton.qml
中加载配置对象,而在 SimpleMainWindow.qml
中不可见。
要做到这一点 TestViewButton.qml
在加载时必须有自己的 QQmlContext
而不是 rootContext()
.
为了测试我的反应并观察这种行为,我们将创建一个类似的按钮,尝试使用 configurator
,如果按下它,它应该抛出一个错误,指出 属性 不存在但是如果加载的按钮被 QQmlComponent
按下应该可以正常工作。
qml/SimpleMainWindow.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Controls 1.4
ApplicationWindow {
id: window
visible: true
width: 640
color: "red"
height: 480
title: qsTr("Hello World")
Button {
x: 100
y: 100
text: "ApplicationWindow"
onClicked: {
console.log("ApplicationWindow")
configurator.sum(1, 2)
configurator.info("TestOutput")
}
}
}
正如我之前评论的那样,我添加了具有新上下文的组件:
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
configurator = SignalHandler()
engine.load("qml/SimpleMainWindow.qml")
engine.quit.connect(app.quit)
rootWindow = engine.rootObjects()[0]
content_item = rootWindow.property("contentItem")
context = QQmlContext(engine)
component = QQmlComponent(engine)
component.loadUrl(QUrl("qml/TestViewButton.qml"))
itm = component.create(context)
context.setContextProperty("configurator", configurator)
itm.setProperty("parent", content_item)
sys.exit(app.exec_())
最后我们得到以下输出:
qml: Component
Adding two numbers
STR TestOutput
qml: ApplicationWindow
file:///xxx/qml/SimpleMainWindow.qml:20: ReferenceError: configurator is not defined
qml: Component
Adding two numbers
STR TestOutput
qml: ApplicationWindow
file:///xxx/qml/SimpleMainWindow.qml:20: ReferenceError: configurator is not defined
我们在哪里观察到期望的行为。完整的例子可以在下面的link.
中找到
我是 Qt/PyQt 的新手,目前正在努力使用一些基本功能。我想做的是,从 python 动态加载 QML-Views (*.qml) 文件并即时替换特定内容。例如,一个复选框被选中,我当前视图的一部分被另一个 qml 文件替换。首先我想通过 PyQt 提供这个逻辑,但似乎 StackView 是一个更好的主意 (multiple qml files in pyqt)。
但是,在这种情况下,我无法将属性注入到我的 QML 文件中。我只能将 属性 注入 rootContext。然而,这限制了我的 QML-Views 的使用,因为我一次只能使用一个视图(相同类型)。我想将属性动态注入 QML-Views 并使它们仅对该特定视图可见。在这种情况下,我可以在后端使用多个对象多次使用相同的视图来捕获信号。
这是我的 SimpleMainWindow.qml 文件(主视图:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Controls 1.4
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
objectName : "WINDOW"
property ApplicationWindow appWindow : window
}
这里是我尝试加载的文件 (TestViewButton.qml):
import QtQuick 2.9
import QtQuick.Controls 1.4
Button {
id: test
text: "test"
objectName : "Button"
onClicked: {
configurator.sum(1, 2)
configurator.info("TestOutput")
}
}
Python 文件加载 QML-View(组件)
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine, QQmlComponent
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load("qml/SimpleMainWindow.qml")
engine.quit.connect(app.quit)
rootWindow = engine.rootObjects()[0].children()[0].parent()
# create component
component = QQmlComponent(engine)
component.loadUrl(QUrl("qml/TestViewButton.qml"))
configurator = SignalHandler()
component.setProperty("configurator", configurator)
itm = component.create()
itm.setParentItem(rootWindow.children()[0])
itm.setProperty("configurator", configurator)
app.exec_()
以及我用来处理来自视图 (SignalHandler.py) 的信号的 python 对象:
from PyQt5.QtCore import QObject, pyqtSlot
class SignalHandler(QObject):
@pyqtSlot(int, int)
def sum(self, arg1, arg2):
print("Adding two numbers")
@pyqtSlot(str)
def info(self, arg1):
print("STR " + arg1)
按钮加载正常(顺便说一句,有没有更好的方法来识别我想添加我的按钮的父级,没有用 findChild 查看)。 component.setProperty..... 部分不起作用。如果我在引擎的 rootContext 中设置 属性 它工作正常(调用 SignalHandler 方法)。已经检查过类似的主题(例如
这可能吗,还是我这里有问题?
谢谢
据我了解,您只想在 TestViewButton.qml
中加载配置对象,而在 SimpleMainWindow.qml
中不可见。
要做到这一点 TestViewButton.qml
在加载时必须有自己的 QQmlContext
而不是 rootContext()
.
为了测试我的反应并观察这种行为,我们将创建一个类似的按钮,尝试使用 configurator
,如果按下它,它应该抛出一个错误,指出 属性 不存在但是如果加载的按钮被 QQmlComponent
按下应该可以正常工作。
qml/SimpleMainWindow.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Controls 1.4
ApplicationWindow {
id: window
visible: true
width: 640
color: "red"
height: 480
title: qsTr("Hello World")
Button {
x: 100
y: 100
text: "ApplicationWindow"
onClicked: {
console.log("ApplicationWindow")
configurator.sum(1, 2)
configurator.info("TestOutput")
}
}
}
正如我之前评论的那样,我添加了具有新上下文的组件:
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
configurator = SignalHandler()
engine.load("qml/SimpleMainWindow.qml")
engine.quit.connect(app.quit)
rootWindow = engine.rootObjects()[0]
content_item = rootWindow.property("contentItem")
context = QQmlContext(engine)
component = QQmlComponent(engine)
component.loadUrl(QUrl("qml/TestViewButton.qml"))
itm = component.create(context)
context.setContextProperty("configurator", configurator)
itm.setProperty("parent", content_item)
sys.exit(app.exec_())
最后我们得到以下输出:
qml: Component
Adding two numbers
STR TestOutput
qml: ApplicationWindow
file:///xxx/qml/SimpleMainWindow.qml:20: ReferenceError: configurator is not defined
qml: Component
Adding two numbers
STR TestOutput
qml: ApplicationWindow
file:///xxx/qml/SimpleMainWindow.qml:20: ReferenceError: configurator is not defined
我们在哪里观察到期望的行为。完整的例子可以在下面的link.
中找到