当前位置: 首页 > news >正文

QML Component 与 Loader 结合动态加载组件

在实际项目中,有时候我们写好一个组件,但不是立即加载出来,而是触发某些条件后才动态的加载显示出来,当处理完某些操作后,再次将其关闭掉;

这样的需求,可以使用 Component 包裹着组件,然后使用 Loader 去动态的加载和关闭;

Component 可以加载任何部件,例如,Rectangle,Button,Image等等

如果需要包裹多个部件,使用 Item {  } 包裹着这些部件即可;

Component {
    Item {
        Rectangle { }
        Button { }
        ......
    }
}

Component 有两个很常用信号,就是创建前触发和销毁前触发,类似构造函数和析构函数,也可以说时回调;

只需要在定义该槽函数即可

Window {
    id: root

    // 窗口创建时触发                                      
    Component.onCompleted: {                        
        root.x = 200                              
        root.y = 200                              
        root.color = "green"                        
        console.log("onCompleted", width, height)   
    }
                                                
    // 窗口销毁时触发                                      
    Component.onDestruction: {                      
        console.log("onDestruction")                
    }  
}                                       

窗口创建销毁前都会去执行相应方法

下面是使用Component加载一个 Rectangle

Component {                                                  
    id: com                                                  
                                                             
    Rectangle {                                              
        id: rect                                             
        width: 200                                           
        height: 100                                          
        color: "red"                                             
    }                                                                                                             
}                                                        

如果直接这样写上去,程序运行后,是不会在窗口中有加载Rectangle出来的,需要使用Loader 去动态加载才行

Loader {                              
    id: loader                        
    sourceComponent: com    // 加载id为 com 的组件                               
}                                     

在Loader中有一个status状态可以用于判断窗口处于哪个阶段;

填写上 onStatusChanged: { } 槽函数,在status状态发生改变时,此槽函数回立即触发;

status 一共有四种状态:

Loader.Null - 未加载 - 0
Loader.Ready - 已加载 - 1
Loader.Loading - 加载中 - 2
Loader.Error - 加载错误 - 3

可以在槽函数中,根据这些状态去做某些相应的操作:

Loader {                                 
    id: loader   
    // 异步加载部件,当这个部件很大时,例如加载很大的图片,或者加载很大的数据,为了不卡死界面,需要使用异步加载  
    asynchronous: true                                     
                                                                                                  
    sourceComponent: com                 
    onStatusChanged: {                   
        console.log("status:", status)   
                                                                   
        if (2 == status) {               
            // 处理一些操作                    
            console.log("加载中...")        
                                         
        } else if (1 == status){         
            // 处理以下操作                    
            console.log("加载完毕.")         
        }                                
    }                                    
}                                    

需要注意的是,加载中,需要在异步加载窗口的时候才会体现出来,即属性 asynchronous: true

当然,也可以在被加载的Rectangle部件中,写上Component.onCompleted: { } 和 Component.onDestruction: { } 

这样当Rectangle被成功加载后,或者被关闭后都会触发槽函数;

Rectangle {                                               
    id: rect                                              
    width: 200                                            
    height: 100                                           
    color: "red"                                          
                                                          
    // 窗口创建时触发                                            
    Component.onCompleted: {                              
        console.log("onCompleted", width, height)         
    }                                                     
                                                          
    // 窗口销毁时触发                                            
    Component.onDestruction: {                            
        console.log("onDestruction")                      
    }                                                     
}                                                       

那么,如何动态的去加载呢?

为了模仿这些场景,我们定义两个按钮,一个用于加载,一个用于关闭;

Button {                                    
    x: 250                                  
    text: "关闭"                              
    onClicked: {                                                                       
        loader.sourceComponent = null                                         
    }                                       
}                                           
                                            
Button {                                    
    x: 250                                  
    y: 100                                  
    text: "显示"                              
    onClicked: {                                                                        
        loader.sourceComponent = com        
    }                                       
}                                            

将sourceComponent 赋值null即可将窗口隐藏,将sourceComponent 赋值Component的id即可加载显示;

现在将Loader中的sourceComponent置null;

Loader {                                 
    id: loader                                                                                                                                 
    sourceComponent: null
    ......
}

当Rectangle被加载出来后,我们还能不能再修改他呢?

答案是可以的!

需要使用到loader.item属性;查看帮助文档介绍:

此属性保存当前加载的顶级对象。

那么也就是说,loader.item 也就相当于rect;即Rectangle的id;

新加第三个按钮,用于测试:

Button {                             
    x: 250                           
    y: 200                           
    text: "修改属性"                     
    onClicked: {                     
        loader.item.width = 50       
        loader.item.height = 50      
        loader.item.color = "green"  
    }                                
}

另外 Loader的source属性可以加载自己编写的qml文件

Loader {
        id: loader
        source: "/MyRectangle.qml"
}

最后是代码分享:

import QtQuick 2.9
import QtQuick.Window 2.2

import QtQuick.Controls 2.2

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

    minimumWidth: 300
    minimumHeight: 400
    maximumHeight: 500
    maximumWidth: 400

    // 透明度
    //opacity: 0.5


    // 窗口创建时触发
//    Component.onCompleted: {
//        root.x = 200
//        root.y = 200
//        root.color = "green"
//        console.log("onCompleted", width, height)
//    }

//    // 窗口销毁时触发
//    Component.onDestruction: {
//        console.log("onDestruction")
//    }


    // Component 可以加载任何部件,然后可以使用 Loader 去动态加载,然后也可以再动态销毁掉
    Component {
        id: com

        Rectangle {
            id: rect
            width: 200
            height: 100
            color: "red"

            // 窗口创建时触发
            Component.onCompleted: {
                console.log("onCompleted", width, height)
            }

            // 窗口销毁时触发
            Component.onDestruction: {
                console.log("onDestruction")
            }
        }

        // Component 内部如果需要添加多个部件,需要使用Item包裹着
//        Item {
//            id: item_id
//            Rectangle {
//                id: rect1
//                width: 60
//                height:60
//                color: "yellow"
//            }
//            Button {
//                id: btn
//                y:100
//                text: "测试按钮"
//            }
//            Image { }
//        }
    }


    Loader {
        id: loader
        // 异步加载部件,当这个部件很大时,例如加载很大的图片,或者加载很大的数据,为了不卡死界面,需要使用异步加载
        asynchronous: true

        //source: "/MyRectangle.qml"
        sourceComponent: com
        onStatusChanged: {
            console.log("status:", status)

            // 加载中
            if (2 == status) {
                // 处理一些操作
                console.log("加载中...")

            } else if (1 == status){
                // 处理以下操作
                console.log("加载完毕.")
            }
        }
    }


    Button {
        x: 250
        text: "关闭"
        onClicked: {
            loader.sourceComponent = null

        }
    }

    Button {
        x: 250
        y: 100
        text: "显示"
        onClicked: {
            loader.sourceComponent = com
        }
    }

    Button {
        x: 250
        y: 200
        text: "修改属性"
        onClicked: {
            loader.item.width = 50
            loader.item.height = 50
            loader.item.color = "green"
        }
    }
}

 

完! 

相关文章:

  • ES6相关操作
  • Typora的Github主题美化
  • 代码随想录算法训练day59---图论系列4
  • 认识HTML的标签结构
  • OpenCV机器学习(8)随机森林(Random Forests)算法cv::ml::RTrees类
  • 美的楼宇科技基于阿里云 EMR Serverless Spark 构建 LakeHouse 湖仓数据平台
  • Github 2025-02-20 Go开源项目日报 Top10
  • GCC编译器(含预处理/编译/汇编/链接四阶段详解)
  • 《耀百岁中医养生平台的技术革命——千年中医的智能觉醒》
  • 【网络编程】服务器模型(一):循环服务器模型和并发服务器模型(多进程)
  • Windows 10操作系统上安装PHP
  • Qt编写守护进程
  • cursor使用记录
  • 第五章 起航11 文章发表
  • 国产编辑器EverEdit - 语法着色及嵌入式多语言着色
  • Day8 25/2/21 FRI
  • GoLang 协程泄漏的原因可能是什么?
  • RTSP场景下RTP协议详解及音视频打包全流程
  • 如何设计提示词让AI以思维链方式回答问题
  • mysql查错误`Error Code: 1248. Every derived table must have its own alias`
  • 戛纳参赛片《爱丁顿》评论两极,导演:在这个世道不奇怪
  • 19世纪的“表征之场”:弗洛伊德的精神分析椅
  • 被央视曝光“废旧厂区沦为垃圾山”,江西萍乡成立调查组查处
  • AI快速迭代带来知识焦虑,褚君浩院士提出“四维能力模型”
  • 牛市早报|上市公司重大资产重组新规出炉,4月经济数据将公布
  • 私家车跑“顺风”出事故,意外险赔不赔?