qml之Loader使用

http://blog.csdn.net/xiangzi_011/article/details/25488137

qml Loader是用来动态加载qml components的,这样就可以在你需要相应的component时才创建它。好处我就不说了。

1.加载方式

Loader可以通过两种方式来加载components,一种是通过source属性来加载一个qml文件(例子1),另一种是通过sourceComponent属性来加载(例子2)。这两种方式都是在鼠标click root后才加载的。

例子1:

import QtQuick 2.2
 
 
Rectangle {
    id:root
    width: 360
    height: 360
 
 
    Loader
    {
        id:loader
    }
 
 
    MouseArea {
        anchors.fill: parent
        onClicked: {
            loader.source = "Page.qml";
        }
    }
}
 
 
 
 
 
例子2:
import QtQuick 2.2
 
Rectangle {
    id:root
    width: 360
    height: 360
 
 
    Loader
    {
        id:loader
    }
 
 
    MouseArea {
        anchors.fill: parent
        onClicked: {
            loader.sourceComponent = component1
        }
    }
 
 
    Component
    {
        id:component1
 
 
        Rectangle {
            width: 100
            height: 62
 
 
            color: "red"
        }
    }
}

2. 位置和大小

通过Loader加载的Component的大小和位置,可以通过Loader来进行设置,如果不设置,则Component会使用默认的大小和位置。

直接看代码:

Rectangle {
    id:root
    width: 200
    height: 200
 
 
    Loader {
        anchors.fill: parent //rect会充满root
        sourceComponent: rect
    }
 
 
    Component {
        id: rect
        Rectangle {
            width: 50
            height: 50
            color: "red"
        }
    }
}
 
Rectangle {
    id:root
    width: 200
    height: 200
 
 
    Loader {
        anchors.centerIn: parent  //rect会处于root的中心
        sourceComponent: rect
    }
 
 
    Component {
        id: rect
        Rectangle {
            width: 50
            height: 50
            color: "red"
        }
    }
}

3. 接收Loader加载的Component的信号

Loader加载的Component发送的任何信号都可以通过Connections方式来处理。target代表发送信号者,这里通过Loader的item属性来获取加载的Component对象,onMessage是对应message信号的处理方法。其实就是一个信号绑定过程。


Rectangle {
 
 
    id:root
    width: 200
    height: 200
 
 
    Loader {
       id: myLoader
       sourceComponent: rect
    }
 
 
    Connections {
        target: myLoader.item   //代表的是rect,但是这里不能直接使用rect,通过Loader加载的对象只能通过item属性进行访问
        onMessage: console.log(msg)
    }
 
 
    Component {
        id: rect
        Rectangle {
 
 
            signal message(string msg)  //声明信号
 
 
            width: 50
            height: 50
            color: "red"
 
 
            MouseArea
            {
                anchors.fill: parent
                onClicked:
                {
                    message("rect clicked!");//发送message信号
                }
            }
        }
    }
}
 
4. Component的销毁
当source或是sourceComponent属性发生变化时,之前加载的项都会被销毁,将source设置成空字符串或是将sourceComponent属性设置成null可以销毁当前已经加载的项,释放Loder所占用的资源。下面例子点击root时会进行判断,如果loader.sourceComponent为null,就设置成component1,component创建,log里输出 " component1onCompleted",如果不为空,就设置为null,就会销毁component,log里输出 " component1 onDestruction"。可见component1对象已经被销毁。
Rectangle {
    id:root
    width: 360
    height: 360
 
 
    Loader
    {
        id:loader
    }
 
 
    MouseArea {
        anchors.fill: parent
        onClicked: {
            loader.sourceComponent = (loader.sourceComponent==null)? component1:null
        }
    }
 
 
    Component
    {
        id:component1
 
 
        Rectangle {
            width: 100
            height: 62
 
 
            color: "red"
 
 
            Component.onCompleted:
            {
                console.log("component1 onCompleted");
            }
            Component.onDestruction:
            {
                console.log("component1 onDestruction");
            }
        }
 
 
    }
}

5. 从QtQuick 2.0以后,Loader可以加载任何qml中的类型,包括QtObject,Timer等非可视化的元素。下面例子中就是实现在一个Text中显示当前的时间。

Rectangle {
 
 
    id:root
    width: 200
    height: 200
 
 
    Text {
        id: text
        anchors.fill: parent
        color: "red"
        text: myLoader.item.displayTime  //通过myLoader.item访问Timer的displayTime属性
    }
 
 
    Loader {
       id: myLoader
       sourceComponent:
           Component {
 
 
           id:noVisualComponent
 
 
           Timer {
               property string displayTime:Date().toString()
               interval: 500; running: true; repeat: true
               onTriggered: displayTime = Date().toString()
           }
       }
    }
}
 
6.  焦点和键盘事件
Loader是一个焦点区域,如果想让Loader的子item获得活动的焦点,必须将Loader的focus属性设置为真。同时如果Loader的子item将accepted属性设置为true后,Loader所在的Item将捕捉不到相应的事件。
下面的例子就是root item鼠标按下前可以捕获按键事件,当鼠标按下后,myComponent被创建,注意Loader和Loader的子item的focus属性都要设置为true。将myComponent中event.accepted = true;改为event.accepted = false; 那么键盘事件会继续传播到root item。
import QtQuick 2.0
 
 
Rectangle {
    width: 200; height: 200
 
 
    Loader {
        id: loader
        focus: true
    }
 
 
    MouseArea {
        anchors.fill: parent
        onClicked: loader.sourceComponent = myComponent;
    }
 
 
    Keys.onPressed: {
        console.log("root Item captured:", event.text);
    }
 
 
    Component
    {
        id:myComponent
        Item {
            Item {
                focus: true
                Keys.onPressed: {
                    console.log("Loaded item captured:", event.text);
                    event.accepted = true;
                }
            }
        }
    }
}

7. 在view delegate中使用Loader

我们可以在ListView的delegate中使用Loader动态的创建Component,来优化ListView的加载性能。这里需要注意: delegateComponent上下文中的 context 属性的访问限制问题。直接上官网给的代码。

<span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">Item</a></span> {
    <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">width</span>: <span class="number">400</span>
    <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">height</span>: <span class="number">400</span>

    <span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">Component</a></span> {
        <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">id</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">myComponent</span>
        <span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">Text</a></span> { <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">text</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">index</span> }    <span class="comment">//Text无法访问到delegateComponent中的index属性
</span>    }

    <span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">ListView</a></span> {
        <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">anchors</span>.fill: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">parent</span>
        <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">model</span>: <span class="number">5</span>
        <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">delegate</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">Component</span> {
            <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">id</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">delegateComponent</span>
            <span class="type" style="color: rgb(128, 128, 128);">Loader</span> {
                <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">sourceComponent</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">myComponent</span>
            }
        }
    }
}

如果想解决这个问题,大概有三种方式。

1)可以将delegateComponent改为inline形式

<span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">delegate</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">Component</span> {
            <span class="type" style="color: rgb(128, 128, 128);">Loader</span> {
                <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">sourceComponent</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">Component</span> {
                    <span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">Text</a></span> { <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">text</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">index</span> }    <span class="comment">//这里Text可以直接访问index属性了</span>
                }
            }
        }
2)将delegateComponent实现到一个单独的qml文件中

 <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">delegate</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">Component</span> {
            <span class="type" style="color: rgb(128, 128, 128);">Loader</span> {
                <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">source</span>: <span class="string">"MyComponent.qml"</span> 
            }
        }

  myComponent.qml中的Text元素中可以直接访问index属性

3)给Loader增加自定义属性,

<span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">Item</a></span> {
    <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">width</span>: <span class="number">400</span>
    <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">height</span>: <span class="number">400</span>

    <span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">Component</a></span> {
        <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">id</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">myComponent</span>
        <span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">Text</a></span> { <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">text</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">modelIndex</span> }    <span class="comment">//这里可以正常访问Loader自定义属性了</span>
    }

    <span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">ListView</a></span> {
        <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">anchors</span>.fill: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">parent</span>
        <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">model</span>: <span class="number">5</span>
        <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">delegate</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">Component</span> {
            <span class="type" style="color: rgb(128, 128, 128);">Loader</span> {
                property <span class="type" style="color: rgb(128, 128, 128);"><a target=_blank target="_blank" href="http://blog.csdn.net/xiangzi_011/article/details/25488137" style="color: rgb(0, 115, 48); text-decoration: none;">int</a></span> <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">modelIndex</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">index //自定义属性,绑定index</span>
                <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">sourceComponent</span>: <span class="name" style="max-width: 75%; color: rgb(26, 26, 26);">myComponent</span>
            }
        }
    }
}

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值