19. 利用Loader和Component重复使用其他页面中动态生成的组件

效果展示:

loader与component结合使用重复使用页面

1. 使用场景:

在某个界面 M 中,我们需要使用动态创建组件的方式来生成一个自定义的控件或者页面 A ,同时会在这个新生成的页面 A 中绑定一些数据之类的内容,一般情况下,当不需要这个页面时,我们会对其使用 destroy() 进行销毁。但是,在某些情况下我们需要在其他界面 N 中也要使用这个动态创建的组件 A (注意:此时的组件已经在某个页面 M 中创建完毕),且要保留 A 里面的完整信息,如果在要使用的这个页面 N 中依然使用动态创建的方法,则生成的是一个新的组件 B , 并被能达到要求。本文提供一种思路来解决这个问题。

2. 实现思路:

2.1 创建 pageA.qml 页面

在这个页面中动态生成 newPage.qml ,并动态生成页面 pageB.qml,因为要保证一些属性的正常使用,详情请看注释,相关代码如下:

import QtQuick 2.15
import QtQuick.Controls 2.15

Item {
    id:pageARoot
    anchors.fill: parent

    property Component newPageCom:null
    property QtObject newPageObj: null
    Rectangle{
        anchors.fill: parent
        color: "lightblue"
    }

    Button{
        id:changePageB
        width: 100
        height: 50
        text: "显示页面B"
        onClicked: {
            pageARoot.visible = false
            //动态生成PageB添加到主界面root中
            //(保证pageARoot在pageB页面生成之前已经存在)
            var pageBCom = Qt.createComponent("qrc:/PageB.qml")
            var pageBObi = pageBCom.createObject(root)
        }
    }

    Rectangle{
        id:container
        width: 200
        height: 200
        anchors.centerIn: parent
        border.width: 1
        border.color: "red"
        Component.onCompleted: {
            newPageCom = Qt.createComponent("qrc:/NewPage.qml")
            newPageObj = newPageCom.createObject(container)
        }
    }
}

2.2 创建 newPage.qml 页面

这个页面就是需要重复使用的,代码如下:里面有个输入框,可以输一些信息,证明在页面B使用时是页面A已生成的组件

import QtQuick 2.15
import QtQuick.Controls 2.15

Item {
    id:dynamicPage
    anchors.fill: parent

    Rectangle{
        id:contentRect
        anchors.fill: parent
        color: "lightgreen"
        Text {
            id: txt
            anchors.centerIn: parent
            text: qsTr("这是动态生成的页面")
        }
        TextField{
            id:input
            anchors.top: txt.bottom
            anchors.bottomMargin: 5
            anchors.left: txt.left
            anchors.right: txt.right
            height: 30
        }
    }
}

2.3 创建 pageB.qml 页面

在这个页面中,使用 Loader 和 Component 完成已生成组件的加载问题,详细代码如下:

import QtQuick 2.15
import QtQuick.Controls 2.15

Item {
    id:pageBRoot
    anchors.fill: parent
    Rectangle{
        anchors.fill: parent
        color: "lightyellow"
    }

    //newPage在PageA中已经动态生成过了,而且界面中填入一些信息
    //在PageB页面中需要PageA中生成的newPage页面的信息,需要在PageB
    //中使用newPage
    //下面这种方式不可行,报错
    //        pageA.newPageObj{

    //        }
    //下面这种方式也不可行,这中方式相当于是生成一个新的newPage页面
    //        NewPage{

    //        }
    //下面的方法可行:
    Loader{
        width: 200
        height: 200
        anchors.centerIn: parent
        sourceComponent: com
    }
    Component{
        id:com
        SplitView{  //这个容器可以自由选择,只要能够将组件添加到容器中就行
            id:splitView
            orientation: Qt.Horizontal
            anchors.fill: parent
            Component.onCompleted: {
                //要保证 pageARoot 这个属性在之前已经生成了
                if(pageARoot.newPageObj !== null){
                    splitView.addItem(pageARoot.newPageObj)
                }
            }
        }
    }
}

2.4 在 main.qml 页面中使用

本文案例,使用时,只需要添加 pageA 即可:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15

Window {
    id:root
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello Quick3D")

    PageA{

    }
}

持续更新中,请大家多多关注…

你可能感兴趣的:(QML常用技巧汇总,qt,ui,开发语言)