Qt QML:可重用对象的文件内定义
Qt QML: in-file definition of reusable objects
我有一个相当大的 Qml 组件,因此我想使它成为一个可重用的组件,但它太大 small/non-generic 以至于我想避免创建自己的 .qml 文件。
似乎组件是在同一个文件中定义可重用对象的正确方法,但是当我这样做时,我不知道如何访问和更改所包含对象的属性。
更具体地说,想象一下有这样一个文件内定义
Component {
id: myReusableComponent
// This cannot be set because component does not allow properties
// (Would work fine in a separate file myReusableComponent.qml)
// property alias string innerText: innerText.text
Rectangle {
id: rect
width: 200
height: 200
color: "red"
Text {
id: innerText
text: "Want to set text later"
}
}
我以后如何重用这个组件,同时改变它的一些属性?
我知道以下语法无效,但我想像这样使用它:
Loader {
id: hello
sourceComponent: myReusableComponent
item.innerText: "Hello" }
Text { text: "Some other stuff in between" }
Loader {
id: world
sourceComponent: myReusableComponent
item.anchors.left: hello.right
item.rect.width: 100
item.rect.color: "blue"
item.innerText: "World" }
Loader {
id: excl
sourceComponent: myReusableComponent
item.rect.color: "green"
item.innerText: "!!!" }
etc...
有什么想法吗?还是有根本不同的方式来做到这一点?
我本质上想要的是就地定义的 QML 对象的可重用性,同时仍然能够更改它们的属性。
好像有关系但是没有解决创建多个对象的问题。中继器似乎很有用,但没有给我想要的灵活性。
注意:我将在此处添加一些关于答案的评论,因为它们可能会在评论中被忽略。
我喜欢 Blabbouze、derM 和 ddriver 的所有三个答案!
我接受了 Blabbouze 的回答,因为它提供了一个最接近我所寻找的具体解决方案。
但是,我也不知道 Loaders 的开销,可能会在阅读 derM 的回答后考虑使用不同的方法。
最后,ddriver 建议的动态对象创建并不是我想要的,但可能对其他人有用。
谢谢大家!
我认为您正在寻找 onLoaded()
信号。当 Loader
成功创建 Component
.
时发出
然后您可以使用 item
访问您加载的类型属性。
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component {
id: myReusableComponent
Rectangle {
id: rect
property alias innerText: innerText.text
width: 200
height: 200
color: "red"
Text {
id: innerText
text: "Want to set text later"
}
}
}
Loader {
id: hello
sourceComponent: myReusableComponent
onLoaded: {
item.innerText = "hello"
}
}
Loader {
id: world
sourceComponent: myReusableComponent
anchors.left: hello.right
onLoaded: {
item.width = 100
item.color = "blue"
item.innerText = "World"
}
}
}
您也可以尝试对组件使用动态对象创建。
所以你可以有一个property Rectangle obj: null
,然后:
Component.onCompleted: {
obj = myReusableComponent.createObject(parentItem, {"width" : 100, "color" : "blue" }
}
除了 Blabbouze 的回答之外,除了作业(不会自动更新为绑定)之外,如果您使用以下格式,您还可以拥有绑定:
item.prop = Qt.binding(function() { bindingExpressions... })
首先我会尝试解释为什么你不想这样做
如果组件被重用 - 即使在一个文件中,而不仅仅是通过 Repeaters
、ListViews
e.t.c - 你应该考虑创建一个单独的文件,以保持你的文件干净且可读。
如果您创建内联组件,然后通过 Loader
创建实例只是为了能够创建它们,它们会带来开销,如果组件确实是可以容忍的巨大的,或者你真的需要 Loader
来动态更改源的可能性。否则,它只会帮助您使一切变得复杂,并增加资源消耗。
将代码放到多个文件中几乎没有任何惩罚。所以这样做,当你有一个合理的、逻辑上封闭的单元时——尤其是当你要在一个文件中多次重复使用它时。
如果您打算将其用作 delegate
,请使用 Component
。有些人喜欢直接在使用它的地方声明 delegate
。如果要设置的属性很少,我会这样做。
特别是如果你有多个 Views
共享相同的 delegate
-prototype,使用 Component
.
是个好主意
如果你真的需要使用 Loader
(因为你需要 Loader
而不是为了创建非动态对象)那么你可以使用 Component
来避免onLoaded
事件的需要。它使您能够 预配置 组件,并在不需要 Connections
-Object 的情况下设置事件处理程序。
好的 - 现在对您问题的简短回答:
您可以通过多种方式创建组件的实例:
- 加载器
- 视图(ListView、GridView、Repeater ...)
- 在任何可以执行 JS 代码的地方使用 JS (
componentID.createObject(parent)
) 创建动态对象。
阅读:http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html#creating-objects-dynamically
我有一个相当大的 Qml 组件,因此我想使它成为一个可重用的组件,但它太大 small/non-generic 以至于我想避免创建自己的 .qml 文件。 似乎组件是在同一个文件中定义可重用对象的正确方法,但是当我这样做时,我不知道如何访问和更改所包含对象的属性。
更具体地说,想象一下有这样一个文件内定义
Component {
id: myReusableComponent
// This cannot be set because component does not allow properties
// (Would work fine in a separate file myReusableComponent.qml)
// property alias string innerText: innerText.text
Rectangle {
id: rect
width: 200
height: 200
color: "red"
Text {
id: innerText
text: "Want to set text later"
}
}
我以后如何重用这个组件,同时改变它的一些属性? 我知道以下语法无效,但我想像这样使用它:
Loader {
id: hello
sourceComponent: myReusableComponent
item.innerText: "Hello" }
Text { text: "Some other stuff in between" }
Loader {
id: world
sourceComponent: myReusableComponent
item.anchors.left: hello.right
item.rect.width: 100
item.rect.color: "blue"
item.innerText: "World" }
Loader {
id: excl
sourceComponent: myReusableComponent
item.rect.color: "green"
item.innerText: "!!!" }
etc...
有什么想法吗?还是有根本不同的方式来做到这一点?
我本质上想要的是就地定义的 QML 对象的可重用性,同时仍然能够更改它们的属性。
注意:我将在此处添加一些关于答案的评论,因为它们可能会在评论中被忽略。 我喜欢 Blabbouze、derM 和 ddriver 的所有三个答案! 我接受了 Blabbouze 的回答,因为它提供了一个最接近我所寻找的具体解决方案。 但是,我也不知道 Loaders 的开销,可能会在阅读 derM 的回答后考虑使用不同的方法。 最后,ddriver 建议的动态对象创建并不是我想要的,但可能对其他人有用。 谢谢大家!
我认为您正在寻找 onLoaded()
信号。当 Loader
成功创建 Component
.
然后您可以使用 item
访问您加载的类型属性。
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component {
id: myReusableComponent
Rectangle {
id: rect
property alias innerText: innerText.text
width: 200
height: 200
color: "red"
Text {
id: innerText
text: "Want to set text later"
}
}
}
Loader {
id: hello
sourceComponent: myReusableComponent
onLoaded: {
item.innerText = "hello"
}
}
Loader {
id: world
sourceComponent: myReusableComponent
anchors.left: hello.right
onLoaded: {
item.width = 100
item.color = "blue"
item.innerText = "World"
}
}
}
您也可以尝试对组件使用动态对象创建。
所以你可以有一个property Rectangle obj: null
,然后:
Component.onCompleted: {
obj = myReusableComponent.createObject(parentItem, {"width" : 100, "color" : "blue" }
}
除了 Blabbouze 的回答之外,除了作业(不会自动更新为绑定)之外,如果您使用以下格式,您还可以拥有绑定:
item.prop = Qt.binding(function() { bindingExpressions... })
首先我会尝试解释为什么你不想这样做
如果组件被重用 - 即使在一个文件中,而不仅仅是通过 Repeaters
、ListViews
e.t.c - 你应该考虑创建一个单独的文件,以保持你的文件干净且可读。
如果您创建内联组件,然后通过 Loader
创建实例只是为了能够创建它们,它们会带来开销,如果组件确实是可以容忍的巨大的,或者你真的需要 Loader
来动态更改源的可能性。否则,它只会帮助您使一切变得复杂,并增加资源消耗。
将代码放到多个文件中几乎没有任何惩罚。所以这样做,当你有一个合理的、逻辑上封闭的单元时——尤其是当你要在一个文件中多次重复使用它时。
如果您打算将其用作 delegate
,请使用 Component
。有些人喜欢直接在使用它的地方声明 delegate
。如果要设置的属性很少,我会这样做。
特别是如果你有多个 Views
共享相同的 delegate
-prototype,使用 Component
.
如果你真的需要使用 Loader
(因为你需要 Loader
而不是为了创建非动态对象)那么你可以使用 Component
来避免onLoaded
事件的需要。它使您能够 预配置 组件,并在不需要 Connections
-Object 的情况下设置事件处理程序。
好的 - 现在对您问题的简短回答:
您可以通过多种方式创建组件的实例:
- 加载器
- 视图(ListView、GridView、Repeater ...)
- 在任何可以执行 JS 代码的地方使用 JS (
componentID.createObject(parent)
) 创建动态对象。
阅读:http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html#creating-objects-dynamically