欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

QML类型——Component

程序员文章站 2024-01-02 21:03:40
...

正文

Component是封装好的,定义明确接口的QML类型,可以重用。
组件通常是由组件文件(即.qml文件)定义。Component类型实质上允许在QML文件中内联定义QML组件,而不是将其定义为单独的QML文件。
应用场景:
1.有重用性且比较小的组件。
2.从逻辑上来看属于某个QML文档的组件。
例如,下面是多个Loader对象加载的组件:

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 }
}

请注意,虽然Rectangle本身会自动呈现展示,但上述矩形并非如此,因为它是内联组件。该组件将QML类型封装起来,就好像它们是在一个独立的QML文档中定义一样,并且直到请求时才会被加载(用Loader对象加载)。由于Component不是从Item派生的,因此无法将任何内容锚定到它。

定义一个内联组件就类似于定义一个QML文档。QML文档只有一个父项,它定义了该组件的行为和属性,并且不能在父项之外定义属性或行为。同样,Component也只能定义一个父项(上例中的Rectangle),并且不能在父项外定义任何数据,但id除外(上例中的redSquare)。

Component类型通常用于为视图(view)提供图形组件。例如,ListView::delegate属性就需要一个Component来指定如何呈现列表的每一项。

Component还可以使用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

组件url,用于构造组件的url。

信号

  • completed()

对象实例化完成时发送该信号。一旦建立了完整的QML环境,就可以在启动时用来执行脚本代码。
可以在任何对象上声明onCompleted信号处理程序。运行处理程序的顺序是不确定的。

Rectangle {
    Component.onCompleted: console.log("Completed Running!")
    Rectangle {
        Component.onCompleted: console.log("Nested Completed Running!")
    }
}
  • destruction()

当对象开始销魂时发送信号。此信号可用于撤销响应completed()信号或应用程序中其他命令性代码完成的工作。
可以在任何对象上声明onDestruction信号处理程序。运行处理程序的顺序是不确定的。

Rectangle {
    Component.onDestruction: console.log("Destruction Beginning!")
    Rectangle {
        Component.onDestruction: console.log("Nested Destruction Beginning!")
    }
}

方法

  • object createObject(parent,object properties)

创建并返回此组件的对象实例,该实例将具有给定的parent和properties。properties参数是可选的。如果对象创建失败,则返回null。

在和创建组件相同的上下文中创建对象,在QML中调用未创建的组件时,此函数将始终返回null。
如果要创建对象但不设置父对象,则需要给parent设置null。如果要显示返回的对象,则在创建时必须提供有效的parent对象,或者给返回的对象设置parent属性,否则该对象将不可见。

如果未给createObject()提供parent对象,则必须保留对返回对象的引用,使它不会被垃圾收集器破坏。无论是否随后设置了Item::parent,这都是正确的,因为设置了Item::parent不会更改对象所有权,仅图形的parent被更改。

从QtQuick1.1开始,此方法接受properties参数可选,该参数指定所创建对象的初始属性。在定义了很多属性值的情况下,设置初始属性值更为有效。并且还允许在创建对象之前设置属性绑定(使用Qt.binding)。
例如下面的代码创建一个对象,其x和y初始值分别为100和100:

var component = Qt.createComponent("Button.qml");
if (component.status == Component.Ready)
    component.createObject(parent, {x: 100, y: 100});

使用destroy()方法可以删除动态创建的实例,请参考从JavaScript动态创建QML对象

  • string errorString()

返回所有错误的描述。
该字符串包括每个错误的文件、位置和描述。如果存在多个错误,则用换行符分隔。
如果没有错误,则返回一个空字符串。

  • object incubateObject(parent, object properties, enumeration mode)

为该组件的实例创建一个孵化器(参考QQmlIncubator)。孵化器允许使用应用程序空闲事件异步创建组件,并且不会导致UI阻塞。
parent参数指定创建的实例的parent。省略参数或传递null,将创建一个没有parent的对象,在这种情况下,必须保留对创建的对象的引用,以避免垃圾回收器释放它。
properties参数指定初始化属性值,在创建对象时对其设置。
mode参数可以是Qt.Synchronous或Qt.Asynchronous,控制实例是同步还是异步创建。默认为Qt.Asynchronous(异步)。在某些情况下,即使指定了Qt.Synchronous,孵化器也可能异步创建对象,例如调用incubateObject()的组件本身是异步创建的。
这三个参数都是可选的。
如果成功,则返回创建该组件的孵化器对象,否则返回null。
孵化器对象具有以下特效:
1.status - 孵化器的状态,有效值:Component.Ready,Component.Loading和Component.Error。
2.object - 创建的对象示例。只有在孵化器状态为Ready时可用。
3.onStatusChanged - 状态更改时响应的函数,status参数返回新状态。
4.forceCompletion() - 强制同步创建所有在孵化器中的对象。调用返回后,孵化器将不会处于Loading状态。
以下示例演示了如何使用孵化器:

var component = Qt.createComponent("Button.qml");

var 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!");
}
相关标签: QML qml

上一篇:

下一篇: