组件是可重用的、封装的 QML 类型,具有定义明确的接口。
组件通常由组件文件(即 .qml 文件)定义。组件类型基本上允许 QML 组件在 QML 文档中内嵌定义,而不是作为单独的 QML 文件。这对于在一个 QML 文件中重复使用一个小组件,或定义一个在逻辑上属于文件中其他 QML 组件的组件可能很有用。
例如,这里有一个由多个装载机对象使用的组件。它只包含一个项目,即一个矩形:
import QtQuick 2.0
Item {
width: 100; height: 100
Component {
id: redSquare
Rectangle {
color: "red"
width: 10
height: 10
}
}
Loader { sourceComponent: redSquare }
Loader { sourceComponent: redSquare; x: 20 }
}
结果:
请注意,虽然矩形本身会自动渲染和显示,但上述矩形并非如此,因为它是在组件中定义的。该组件封装了其中的 QML 类型,就像它们是在一个单独的 QML 文件中定义的一样,而且直到被请求(在本例中,被两个加载器对象请求)时才会被加载。因为 Component 不是从 Item 派生的,所以不能锚定任何东西。
定义 Component 与定义 QML 文档类似。一个 QML 文档有一个顶层项,它定义了该组件的行为和属性,而不能在该顶层项之外定义属性或行为。同样,一个组件的定义也包含一个顶层项(在上例中是一个矩形),除了一个 id(在上例中是 redSquare)外,不能在这个顶层项之外定义任何数据。
组件类型通常用于为视图提供图形组件。例如,ListView::delegate 属性需要一个组件来指定如何显示每个列表项。
也可以使用 Qt.createComponent() 动态创建组件对象。
创建上下文
组件的创建上下文与组件的声明上下文相对应。当该组件被 ListView 或 Loader 等对象实例化时,该上下文将被用作父上下文(创建上下文层次结构)。
在下面的示例中,comp1 是在 MyItem.qml 的根上下文中创建的,从该组件实例化的任何对象都可以访问该上下文中的 id 和属性,如 internalSettings.color。当 comp1 在其他上下文(如下面的 main.qml)中作为 ListView 委托使用时,它将继续访问其创建上下文中的属性(否则外部用户将无法访问这些属性)。
MyItem.qml
Item {
property Component mycomponent: comp1
QtObject {
id: internalSettings
property color color: "green"
}
Component {
id: comp1
Rectangle { color: internalSettings.color; width: 400; height: 50 }
}
}
main.qml
ListView {
width: 400; height: 400
model: 5
delegate: myItem.mycomponent //will create green Rectangles
MyItem { id: myItem }
}
创建上下文的生命周期必须长于任何已创建对象的生命周期。详情请参阅维护动态创建的对象。
属性
progress:real
加载组件的进度,从 0.0(未加载)到 1.0(已完成)。
status:enumeration
此属性显示组件加载的状态。状态可以是以下之一:
Component.Null 该组件没有可用数据
Component.Ready 该组件已加载,可用于创建实例。
Component.Loading 当前正在加载组件
Component.Error 加载组件时发生错误。调用 errorString() 将提供关于任何错误的可读描述。
url:url
信号
completed()
在对象实例化后发出。一旦建立了完整的 QML 环境,它就可以用来在启动时执行脚本代码。
onCompleted 信号处理程序可在任何对象上声明。处理程序的运行顺序未定义。
注:相应的处理程序是 onCompleted。
Rectangle {
Component.onCompleted: console.log("Completed Running!")
Rectangle {
Component.onCompleted: console.log("Nested Completed Running!")
}
}
destruction()
在对象开始销毁时发出。它可用于撤销响应 completed() 信号时已完成的工作,或应用程序中的其他命令代码。
onDestruction 信号处理程序可以在任何对象上声明。处理程序的运行顺序未定义。
注:相应的处理程序是 onDestruction。
方法
Qtobject createObject(QtObject parent,object properties)
QtObject createObject(QtObject 父对象,对象属性)
创建并返回该组件的对象实例,该实例将具有给定的父对象和属性。属性参数是可选的。如果对象创建失败,则返回 null。
对象将在与创建组件时相同的上下文中创建。当调用非 QML 创建的组件时,此函数将始终返回空值。
如果想创建对象而不设置父对象,可指定父对象值为 null。请注意,如果要显示返回的对象,您必须提供一个有效的父对象值或设置返回对象的父对象属性,否则该对象将不可见。
如果未向 createObject() 提供父对象,则必须保留返回对象的引用,以免垃圾回收器将其销毁。无论之后是否设置 Item::parent 都是如此,因为设置 Item 父对象并不会改变对象的所有权。改变的只是图形父对象。
从 QtQuick 1.1 开始,该方法接受一个可选的 properties 参数,该参数指定了创建对象的初始属性值映射。这些值将在对象创建最终完成前应用。这比在创建对象后设置属性值更有效,尤其是在定义了大量属性值集的情况下,而且还允许在创建对象前设置属性绑定(使用 Qt.binding)。
属性参数指定为属性值项的映射。例如,下面的代码创建了一个对象,其初始 x 值和 y 值分别为 100 和 100:
const component = Qt.createComponent("Button.qml");
if (component.status === Component.Ready) {
component.createObject(parent, { x: 100, y: 100 });
}
动态创建的实例可以用 destroy() 方法删除。更多信息,请参阅从 JavaScript 动态创建 QML 对象。
string errorString()
返回对任何错误的可读描述。
字符串包括文件、位置和每个错误的描述。如果出现多个错误,则以换行符分隔。
如果没有错误,则返回空字符串。
object incubateObject(QtObject parent,object properties, enumeration mode)
为该组件实例创建一个孵化器。孵化器允许异步实例化新的组件实例,并且不会导致用户界面冻结。
父参数指定创建实例的父对象。省略该参数或传递空值将创建一个没有父对象的对象。在这种情况下,必须保留对创建对象的引用,以免垃圾回收器将其销毁。
属性参数被指定为属性值项的映射,这些值项将在创建对象时设置。模式可以是 Qt.Synchronous 或 Qt.Asynchronous,并控制实例是同步创建还是异步创建。默认为异步。在某些情况下,即使指定了 Qt.Synchronous,孵化器也可能以异步方式创建对象。如果调用 incubateObject() 的组件本身是异步创建的,就会出现这种情况。
所有三个参数都是可选的。
如果创建成功,该方法将返回一个孵化器,否则返回空。孵化器具有以下属性:
status - 孵化器的状态。有效值为 Component.Ready、Component.Loading 和 Component.Error。
object - 创建的对象实例。只有当孵化器处于就绪状态时才可用。
onStatusChanged - 指定状态改变时调用的回调函数。状态将作为参数传递给回调函数。
forceCompletion() - 调用以同步完成孵化。
下面的示例演示了如何使用孵化器:
const component = Qt.createComponent("Button.qml");
const incubator = component.incubateObject(parent, { x: 10, y: 10 });
if (incubator.status !== Component.Ready) {
incubator.onStatusChanged = function(status) {
if (status === Component.Ready) {
print("Object", incubator.object, "is now ready!");
}
};
} else {
print("Object", incubator.object, "is ready immediately!");
}
动态创建的实例可以用 destroy() 方法删除。