QML学习之Compoment和Qt.createComponent

博客介绍了在QML中创建和使用Component的方法。有两种创建方式,一是用Qt.createComponent加载qml文件创建,二是用Qt.createQmlObject从qml字符串创建。创建后需调用createObject创建可用对象,销毁时调用对象的destroy方法,同时要检查Component的status属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看代码:TestCompont.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4

Rectangle {
    id: compontRect
    color: Qt.rgba(0.8, 0.4, 0.4, 1.0)
    implicitWidth: 200
    implicitHeight: 50
    property var currentObject: ;

    signal deleteThis(var obj)

    // 设置文字的内容
    function setCurrentText(textName) {
        interText.text = textName
    }

    Text {
        id: interText
        anchors.left: parent.left
        anchors.leftMargin: 10
        anchors.verticalCenter: parent.verticalCenter
        text: qsTr("text")
    }
    Button {
        anchors.margins: 5
        anchors.top: parent.top
        anchors.bottom: parent.bottom
        anchors.right: parent.right
        text: '删除'

        onClicked: {
            compontRect.deleteThis(compontRect)
        }
    }

    Component.onCompleted: {
        compontRect.currentObject = parent
    }
}

main.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4

Window {
    width: 800
    height: 600
    visible: true

    Rectangle {
        id: mainRect
        anchors.fill: parent
        property Component mainRectComponent: null

        Column {
            id: mainColumn
            spacing: 5

            width: parent.width
            property real count: 0

            function deleteItems(object) {
                object.destroy()
            }

            function createItem() {
                var color = 'red'
                if (mainColumn.count % 3 === 1)
                    color = 'yellow'
                else if (mainColumn.count % 3 === 2)
                    color = 'blue'
                mainColumn.count++

                // 本文件中创建并返回一个组件的实例
                var obj = itemCompont.createObject(mainColumn, {"color": color, "width": mainRect.width})
                //obj.setCurentObject(obj)
                obj.setCurrentText('Component' + mainColumn.count.toString())
                obj.deleteThis.connect(mainColumn.deleteItems)



                // 其它文件中创建并返回一个组件的实例
                var obj2 = mainRect.mainRectComponent.createObject(mainColumn,
                                                        {'color': Qt.rgba(0.4, 0.8, 0.6, 1.0)
                                                        ,'width': mainRect.width})
                obj2.setCurrentText('Component' + mainColumn.count.toString() + ', From File TestComponent')
                obj2.deleteThis.connect(mainColumn.deleteItems)
            }
        }

        Button {
            anchors.top: mainColumn.bottom
            anchors.topMargin: 10
            anchors.right: mainRect.right
            anchors.rightMargin: 10
            text: '添加'

            onClicked: {
                mainColumn.createItem()
            }
        }

        Component.onCompleted: {


            if (mainRectComponent === null)
            {
                console.log("-----createComponent....------");
                mainRectComponent = Qt.createComponent("TestCompont.qml");
            }
        }

        Component {
            id: itemCompont
            Rectangle {
                id: compontRect
                color: 'blue'
                implicitWidth: 200
                implicitHeight: 50
                property var currentObject: ''

                signal deleteThis(var obj)

                // 设置文字的内容
                function setCurrentText(textName) {
                    interText.text = textName
                }

                Text {
                    id: interText
                    anchors.left: parent.left
                    anchors.leftMargin: 10
                    anchors.verticalCenter: parent.verticalCenter
                    text: qsTr("text")
                }
                Button {
                    anchors.margins: 5
                    anchors.top: parent.top
                    anchors.bottom: parent.bottom
                    anchors.right: parent.right
                    text: '删除'

                    onClicked: {
                        compontRect.deleteThis(compontRect)
                    }
                }

                Component.onCompleted: {
                    compontRect.currentObject = parent
                }
            }
        }
    }
}

运行结果:

再看这样的写法:

var editPage = Qt.createComponent("EditPage.qml").createObject(mainPage);

editPage是将要显示的页面;mainPage是editPage的父级页面,也就是editPage返回后的上一级页面。

有两种方法可以创建,都是全局对象Qt提供的方法

一:用Qt.createComponent加载一个qml文件并创建Component

二:用Qt.createQmlObject从一个qml字符串创建Component

注意,以上两种方法返回的是Component,Component在QML中是一种类型,参考文档:

因此还要调用Component的createObject来创建真正可用的对象。createObject第一个参数是指定挂在谁的下方,也就是父窗口是谁。如果传递null,则代表暂时不显示。

如果要销毁,只需要调用对象的destroy方法即可。

调用createObject方法需要注意qml文件已经被加载完成才行,因为这种机制允许远程加载qml文件,所以需要检查Component的status属性:

This property holds the status of component loading. The status can be one of the following:

  • Component.Null - no data is available for the component
  • Component.Ready - the component has been loaded, and can be used to create instances.
  • Component.Loading - the component is currently being loaded
  • Component.Error - an error occurred while loading the component. Calling errorString() will provide a human-readable description of any errors.
在使用Qt QML中的`Qt.createComponent`或`Qt.createObject`创建完对象之后,如果尝试直接调用`open`等函数,而该对象还没有完全初始化或者尚未关联到任何窗口或其他上下文,就可能会遇到"Cannot call method 'open' of null"这样的错误。 这是因为当你试图调用方法前,对象还处于未激活状态,可能原因有以下几点: 1. **创建失败**:检查是否能成功创建组件,`createComponent`返回的是null,意味着没有找到对应模板或者创建过程中发生错误。 ```javascript var component = Qt.createComponent('Path/To/Your.qml'); if (!component) { console.error('Failed to create the component.'); } ``` 2. **生命周期顺序**:确保你在调用`open`之前,对象已经完成实例化并且关联到了一个父节点(例如,Window或Page)。 ```javascript var widget = Qt.createComponent('MyWidget.qml'); // 确保先设置parent节点 var parent = new Qt.QQuickView(); parent.setSource QQmlEngine.rootContext(), QQmlUrl.fromLocalFile('path/to/main.qml'); parent.show(); // 将组件添加到视图中并激活 parent.rootContext().setObject('myWidget', widget); widget.open(); // 现在应该可以正常调用了 ``` 3. **方法的可用性**:确认所使用的组件是否包含`open`这个方法,某些自定义组件可能不会提供这个默认方法。 4. **异常处理**:添加适当的错误处理代码,以便在`open`失败时捕获并报告错误。 如果你遇到了这个问题,最好一步步排查上述可能的原因,并检查日志信息以获取更详细的错误详情。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值