- 细节描述:
- 功能
- 动态加载QML组件
- 加载对象可以为通过URL加载的qml文件,也可以是加载对象组件
- 用于当组件被调用时才创建
- 在处于性能方面考虑下,组件在某些情况下无需被创建的情形下使用该QML对象
- 当使用“item”属性后loader对象才能够被访问
- loader加载其他组件或者其他qml文件后,先前已经实例化了的组件或者qml文件的资源将会被清理
- 利用以上的特性可以将loader的source属性设置为空的string或者设置sourceComponent为undefined将会释放资源空间和离开空的Loader
- Loader的尺寸特性(Loader sizing behavior)
若source Component 加载的是非Item类型时,Loader不应用任何指定的尺寸规则。当用于加载可用类型时,Loader应用如下的尺寸规则:
- 如果Loader没有明确指定尺寸,Loader将会自动地根据加载的组件的Loader Item尺寸来调整大小。
- 如果Loader设置大小规则(height or anchoring)来明确指定尺寸大小,Loader将会根据该尺寸从新调整尺寸大小
- 功能
import QtQuick 2.0
Item {
width: 200; height: 200
Loader {
// Explicitly set the size of the
// Loader to the parent item's size
anchors.fill: parent
sourceComponent: rect
}
Component {
id: rect
Rectangle {
width: 50
height: 50
color: "red"
}
}
}
//由于Loader明确指定尺寸大小,因此Loader将会根据parent的大小来调整Loader的大小;
再来看一个未明确指定大小的例子:
import QtQuick 2.0
Item {
width: 200; height: 200
Loader {
// position the Loader in the center
// of the parent
anchors.centerIn: parent
sourceComponent: rect
}
Component {
id: rect
Rectangle {
width: 50
height: 50
color: "red"
}
}
}
//由于没有明确指定Loader的大小,因此Loader将会根据加载的组件的尺寸规则来调整加载组件的大小。
结论:Loader的尺寸规则优先根据Loader明确指定的尺寸来调整,否则根据加载的组件或者qml文件的尺寸规则来调整显示大小
- Receiving signals from loaded objects(从loaded对象中接受信号)
任何从loaded中发射出来的信号可以使用Connections类来接收。举个例子:以下application.qml 加载Myitem.qml 并且可以通过connections对象来接收来自Loaded Item emit 的message信号
//application.qml
import QtQuick 2.0
Item {
width: 100; height: 100
Loader {
id: myLoader
source: "MyItem.qml"
}
Connections {
target: myLoader.item
onMessage: console.log(msg)
}
}
//MyItem.qml
import QtQuick 2.0
Rectangle {
id: myItem
signal message(string msg)
width: 100; height: 100
MouseArea {
anchors.fill: parent
onClicked: myItem.message("clicked!")
}
}
另外,因为MyItem.qml是在Loader的作用域中加载的,因此它也可以直接调用定义在Loader或者它的父类Item中的函数
- 聚焦和键盘事件(Focus and key events)
Loader 是一个聚焦的范围,它的“focus”属性必须被设置为true,这样它的子类才能够获取它的活动的焦点;在loaded Item中的任何一个键盘事件应该也可以被接收,这样才不会被传播到Loader。
举个例子,以下application.qml 在鼠标点击后加载 KeyReader.qml
注意和动态加载的item一样,Loader的focus属性也设置为true
//application.qml
import QtQuick 2.0
Rectangle {
width: 200; height: 200
Loader {
id: loader
focus: true
}
MouseArea {
anchors.fill: parent
onClicked: loader.source = "KeyReader.qml"
}
Keys.onPressed: {
console.log("Captured:", event.text);
}
}
//KeyReader.qml
import QtQuick 2.0
Item {
Item {
focus: true
Keys.onPressed: {
console.log("Loaded item captured:",
event.text);
event.accepted = true;
}
}
}
一旦KeyReader.qml 被加载后,它将接收键盘事件,设置event.accepted 为true 这样键盘事件将不会被传播到父类的Rectangle
自从QtQuick 2.0 后 Loader可以加载不可见的组件。
- 使用视图代理的Loader(Using a Loader within a view delegate)
在一些希望使用视图代理的Loader来提高代理加载的性能时,在大多数情况下这种方法很有效,但有一个重要的问题:
在以下的例子中,通过ListView插入的index这个上下文属性进入代理的组件的上下文关系中将访问不到Text;原因是:Loader在实例化时,将会使用myComponent 创建的上下文关系作为父类的上下文关系,并且此时index在上下文链路中将不会指向任何东西。
Item {
width: 400
height: 400
Component {
id: myComponent
Text { text: index } //fails
}
ListView {
anchors.fill: parent
model: 5
delegate: Component {
id: delegateComponent
Loader {
sourceComponent: myComponent
}
}
}
}
这种情况下我们可以这样修改:
将加载的组件直接包含在Loader中这样实例化时,Loader的父类的上下文关系链路将会依靠Componect 创建的context,这样index将会指向Component的index
delegate: Component {
Loader {
sourceComponent: Component {
Text { text: index } //okay
}
}
}
或者可以将要加载的组件分离开来:
delegate: Component {
Loader {
source: "MyComponent.qml" //okay
}
}
或者在Loader中将index这种context的属性记录下来。避免Loader依靠所加载的组件生成的context来获取context的属性。
Item {
width: 400
height: 400
Component {
id: myComponent
Text { text: modelIndex } //okay
}
ListView {
anchors.fill: parent
model: 5
delegate: Component {
Loader {
property int modelIndex: index
sourceComponent: myComponent
}
}
}
}
总结: 在使用Model-view-delegate 提高组件性能时,要注意Loader的上下文关系(context)将会依靠加载的组件生成的context,这样可能会导致加载的组件生成的上下文关系中没有context特定的属性或者指向未知位置。
属性:
active : bool
Loader当前是激活时该属性为true,该属性默认值为true
如果Loader 不激活,改变source和sourceComponent 的值后将不会依据Item实例化Loader,除非激活Loader。
设置为非激活,将注销加载器加载的任何Item,当不会对source或者sourceComponent属性产生任何作用。
非激活的Loader的status属性将总会是“null”asynchronous : bool
这个属性决定是否一步实例化组件
当我们和source属性同时用时,加载和编译的工作将会都在后台线程中执行。
Loading 将会异步跨越多个帧来创建由组件定义的对象,这样可以减少动画过渡产生的毛刺
异步加载时,Loader的状态将会变为Loader.Loading
一旦组件的实体被创建后,Item将会可用的并且状态将会变为Loader.Ready.
为了避免看到Items 逐步被加载,可以适当地设置visible这个属性,比如Loader { source: "mycomponent.qml" asynchronous: true visible: status == Loader.Ready } //异步加载完成后,Loader才会被激活
注意这个属性在object实例化过程中才有效,这个属性和通过网络异步加载组件无关
item : object
这个属性控制当前加载器的顶级对象
- progress : real
这个属性控制从网络中加载QML组件的进展,改值从0.0(没有加载)到1.0(加载完成),大多数QML文件都是很小的,因此改值快速地在0.0和1.0之间变化
- progress : real
source : url
控制将要实例化的QML组件的URL
sourceComponect : Componect
控制将要实例化的组件
Item {
Component {
id: redSquare
Rectangle { color: "red"; width: 10; height: 10 }
}
Loader { sourceComponent: redSquare }
Loader { sourceComponent: redSquare; x: 10 }
}status : enumeration
QMl 加载的状态,该状态是以下其中的一项:
- Loader.Null :Loader没有激活或者QML source 没有设置
- Loader.Ready :QML source已经被加载完成。
- Loader.Loading :QML source目前正在加载。
- Loader.Error :加载QML source时发生错误。
发射的信号
- loader()
当status 变为Loader.Ready后或者成功初始化加载后将会发射该信号
相应的处理程序是OnLoaded- loader()
- 使用方法:
- object setSource(url source, object properties)