博客24## 一、Components(组件)

Component 是由 Qt 框架或开发者封装好的、只暴露了必要接口的 QML 类型,可以重复利用。一个 QML 组件就像一个黑盒子,它通过属性、信号、函数和外部世界交互。

一个 Component 即可以定义在独立的 qml 文件中,也可以嵌入到其它的 qml 文档中来定义。通常我们可以根据这个原则来选择将一个 Component 定义在哪里:如果一个 Component 比较小且只在某个 qml 文档中使用或者一个 Component 从逻辑上看从属于某个 qml 文档,那就可以采用嵌入的方式来定义该 Component 。你也可以与 C++ 的嵌套类对比来理解。

嵌入式定义组件

示例 QML 代码如下:

import QtQuick 2.0
import QtQuick.Controls 1.1 Rectangle {
width: 320;
height: 240;
color: "#C0C0C0"; Text {
id: coloredText;
anchors.horizontalCenter: parent.horizontalCenter;
anchors.top: parent.top;
anchors.topMargin: 4;
text: "Hello World!";
font.pixelSize: 32;
} Component {
id: colorComponent;
Rectangle {
id: colorPicker;
width: 50;
height: 30;
signal colorPicked(color clr);
MouseArea {
anchors.fill: parent
onPressed: colorPicker.colorPicked(colorPicker.color);
}
}
} Loader{
id: redLoader;
anchors.left: parent.left;
anchors.leftMargin: 4;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 4;
sourceComponent: colorComponent;
onLoaded:{
item.color = "red";
}
} Loader{
id: blueLoader;
anchors.left: redLoader.right;
anchors.leftMargin: 4;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 4;
sourceComponent: colorComponent;
onLoaded:{
item.color = "blue";
}
} Connections {
target: redLoader.item;
onColorPicked:{
coloredText.color = clr;
}
} Connections {
target: blueLoader.item;
onColorPicked:{
coloredText.color = clr;
}
}
}

如你所见,要在一个 QML 文档中嵌入 Component 的定义,需要使用 Component 对象。

定义一个 Component 与定义一个 QML 文档类似, Component 只能包含一个顶层 item ,而且在这个 item 之外不能定义任何数据,除了 id 。比如上面的代码中,顶层 item 是 Rectangle 对象,在 Rectangle 之外我定义了 id 属性,其值为 colorComponent 。而顶层 item 之内,则可以包含更多的子元素来协同工作,最终形成一个具有特定功能的组件。

Component 通常用来给一个 view 提供图形化组件,比如ListView::delegate属性就需要一个 Component 来指定如何显示列表的每一个项,又比如ButtonStyle::background属性也需要一个 Component 来指定如何绘制 Button 的背景。

Component 不是 Item 的派生类,而是从 QQmlComponent 继承而来,虽然它通过自己的顶层 item 为其它的 view 提供可视化组件,但它本身是不可见元素。你可以这么理解:你定义的组件是一个新的类型,它必须被实例化以后才可能显示。而要实例化一个嵌入在 qml 文档中定义的组件,则可以通过 Loader。后面我们详细讲述 Loader ,这里先按下不表。

二、使用 Loader

2.1 Loader 的详细介绍

Loader 用来动态加载 QML 组件。Loader 可以使用其 source 属性加载一个 qml 文档,也可以通过其 sourceComponent 属性加载一个 Component 对象。当你需要延迟一些对象直到真正需要才创建它们时, Loader 非常有用。

当 Loader 的 source 或 sourceComponent 属性发生变化时,它之前加载的 Component 会自动销毁,新对象会被加载。将 source 设置为一个空字符串或将 sourceComponent 设置为 undefined ,将会销毁当前加载的对象,相关的资源也会被释放,而 Loader 对象则变成一个空对象。

Loader 的 item 属性指向它加载的组件的顶层 item ,比如 Loader 加载了我们的颜色选择组件,其 item 属性就指向颜色选择组件的 Rectangle 对象。对于 Loader 加载的 item ,它暴露出来的接口,如属性、信号等,都可以通过 Loader 的 item 属性来访问。所以我们才可以这么使用:

Loader{
id: redLoader;
anchors.left: parent.left;
anchors.leftMargin: 4;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 4;
sourceComponent: colorComponent;
onLoaded:{
item.color = "red";
}
}

上面的代码在 Loader 对象使用 sourceComponent 属性来加载 id 为 colorComponent 的组件对象,然后在 onLoaded 信号处理器中使用 item 属性来设置颜色选择组件的颜色。对于信号的访问,我们则可以使用 Connections 对象,如下面的 qml 代码所示:

Connections {
target: redLoader.item;
onColorPicked:{
coloredText.color = clr;
}
}

我们创建的 Connections 对象,其 target 指向 redLoader.item ,即指向颜色选择组件的顶层 item — Rectangle ,所以可以直接响应它的 colorPicked 信号。

虽然 Loader 本身是 Item 的派生类,但没有加载 Component 的 Loader 对象是不可见的,没什么实际的意义。而一旦你加载了一个 Component , Loader 的大小、位置等属性却可以影响它所加载的 Component 。

如果你没有显式指定 Loader 的大小,那么 Loader 会将自己的尺寸调整为与它加载的可见 item 的尺寸一致;如果 Loader 的大小通过 width 、 height 或 锚布局显式设置了,那么它加载的可见 item 的尺寸会被调整以便适应 Loader 的大小。不管是哪种情况, Loader 和它所加载的 item 具有相同的尺寸,这确保你使用锚来布局 Loader 就等同于布局它加载的 item 。

2.2 从文件加载组件

之前介绍 Loader 时,我们以嵌入式定义的 Component 为例子说明 Loader 的各种特性和用法,现在我们来看如何从文件加载组件。

对于定义在一个独立文件中的 Component ,同样可以使用 Loader 来加载,只要指定 Loader 的 source 属性即可。现在再来修改下我们的例子,使用 Loader 来加载 ColorPicker 组件。

示例代码如下:

import QtQuick 2.0
import QtQuick.Controls 1.1 Rectangle {
width: 320;
height: 240;
color: "#EEEEEE"; Text {
id: coloredText;
anchors.horizontalCenter: parent.horizontalCenter;
anchors.top: parent.top;
anchors.topMargin: 4;
text: "Hello World!";
font.pixelSize: 32;
} Loader{
id: redLoader;
width: 80;
height: 60;
focus: true;
anchors.left: parent.left;
anchors.leftMargin: 4;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 4;
source: "ColorPicker.qml";
KeyNavigation.right: blueLoader;
KeyNavigation.tab: blueLoader; onLoaded:{
item.color = "red";
item.focus = true;
} onFocusChanged:{
item.focus = focus;
}
} Loader{
id: blueLoader;
focus: true;
anchors.left: redLoader.right;
anchors.leftMargin: 4;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 4;
source: "ColorPicker.qml";
KeyNavigation.left: redLoader;
KeyNavigation.tab: redLoader; onLoaded:{
item.color = "blue";
} onFocusChanged:{
item.focus = focus;
}
} Connections {
target: redLoader.item;
onColorPicked:{
coloredText.color = clr;
if(!redLoader.focus){
redLoader.focus = true;
blueLoader.focus = false;
}
}
} Connections {
target: blueLoader.item;
onColorPicked:{
coloredText.color = clr;
if(!blueLoader.focus){
blueLoader.focus = true;
redLoader.focus = false;
}
}
}
}

代码有几处改动:

一处是将 sourceComponent 修改为 source ,其值为 "ColorPicker.qml" 。

一处是两个 Connections 对象,在 onColorPicked 信号处理器中,设置了 Loader 的焦点属性,因为只有 Loader 有焦点,它加载的 item 才会有焦点,如果你鼠标点击某个颜色选择组件而加载它的 Loader 没有焦点,那么虽然颜色可以改变,但是焦点框出不来。

使用 Loader 加载定义在 qml 文档中的组件,比直接使用组件名构造对象要繁琐得多,但如果你的应用会根据特定的情景来决定某些界面元素是否显示,这种方式也许可以满足你。

参考:

《Qt Quick核心编程》第7章

Qt Quick 组件与对象动态创建详解

Qt Quick 组件与动态对象的更多相关文章

  1. Qt Quick 组件和动态创建的对象具体的解释

    在<Qt Quick 事件处理之信号与槽>一文中介绍自己定义信号时,举了一个简单的样例.定义了一个颜色选择组件,当用户在组建内点击鼠标时,该组件会发出一个携带颜色值的信号,当时我使用 Co ...

  2. Qt Quick 布局演示

    于 Qt Widgets 于,我们经常使用许多布局管理器来管理界面 widgets . 于 Qt Quick 实际上,有两个相关的管理和布局库,所谓集 Item Positioner ,所谓集 Ite ...

  3. Qt Quick实现的涂鸦程序

    之前一直以为 Qt Quick 里 Canvas 才干够自绘.后来发觉不是,原来还有好几种方式都能够画图! 能够使用原始的 OpenGL(Qt Quick 使用 OpenGL 渲染).能够构造QSGN ...

  4. Qt Quick实现的疯狂算数游戏

    使用 Qt Quick 写了个小游戏:疯狂算数.支持 Windows 和 Android 两个平台. 游戏简单,但牵涉到下面你的 Qt Quick 主题: 自己实现一个按钮 自适应分辨率 国际化 QM ...

  5. Qt Quick 事件处理之信号与槽

    前面两篇文章<QML 语言基础>和<Qt Quick 简单教程>中我们介绍了 QML 语言的基本的语法和 Qt Quick 的常见元素,亲们,通过这两篇文章,您应该已经能够完毕 ...

  6. Qt Quick之StackView具体解释(1)

    Qt Quick中有个StackView.我在<Qt Quick核心编程>一书中没有讲到.近期有人问起,趁机学习了一下,把它的基本使用方法记录下来. 我准备分两次来讲.第一次讲主要的使用方 ...

  7. Qt Quick 图像处理实例之美图秀秀(附源代码下载)

    在<Qt Quick 之 QML 与 C++ 混合编程具体解释>一文中我们解说了 QML 与 C++ 混合编程的方方面面的内容,这次我们通过一个图像处理应用.再来看一下 QML 与 C++ ...

  8. Qt Quick综合实例之文件查看器

    假设你基于Qt SDK 5.3.1来创建一个Qt Quick App项目,项目模板为你准备的main.qml文档的根元素是ApplicationWindow或Window.这次我们就以Applicat ...

  9. Qt Quick 之 QML 与 C++ 混合编程具体解释

    Qt Quick 技术的引入.使得你能够高速构建 UI ,具有动画.各种绚丽效果的 UI 都不在话下.但它不是万能的.也有非常多局限性,原来 Qt 的一些技术,比方低阶的网络编程如 QTcpSocke ...

随机推荐

  1. .net core 发布到iis问题 HTTP Error 500.30 - ANCM In-Process Start Failure

    1. 没有在Program里配置IIS webBuilder.UseIIS(); 2. StartupProduction 里AutoFac容器注入错误和新版的CORS中间件已经阻止使用允许任意Ori ...

  2. python 处理中文遇到的编码问题总结 以及 字符str的编码如何判断

    如何处理中午编码的问题 Python的UnicodeDecodeError: 'utf8' codec can't decode byte 0xxx in position 这个错误是因为你代码中的某 ...

  3. mp4文件格式解析二

    目前MP4的概念被炒得很火,也很乱.最开始MP4指的是音频(MP3的升级版),即MPEG-2 AAC标准.随后MP4概念被转移到视频上,对应的是MPEG-4标准.而现在我们流行的叫法,多半是指能播放M ...

  4. Linux性能调优 | 01 平均负载的理解和分析

    01 uptime命令 通常我们发现系统变慢时,我们都会执行top或者uptime命令,来查看当前系统的负载情况,比如像下面,我执行了uptime,系统返回的了结果. [root@lincoding ...

  5. git did not exit cleanly (exit code 1) 的解决办法

    问题描述: 关于Git的使用,在通常情况下,习惯于先在本地创建一个本地仓库,然后将项目提交到本地master,再将本地master中的项目Push 到远程仓库中,这样问题就来了. 具体错误信息如下: ...

  6. 4-7 3D绘图

    In [1]: import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D % ...

  7. Python环境安装与基础语法(4)——内存管理、if分支

    Python内存管理 python中有自动清理内存垃圾的功能,当变量的引用计数为0,则可以被有计划的垃圾回收GC 常量会在系统中被多次引用,所以常量的引用计数无法确定 程序控制 顺序:按照先后顺序逐条 ...

  8. SSM整合开发——基于SSM的OA系统

    一.课程介绍 链接: https://pan.baidu.com/s/18B-lWfOUnKZPvuVEHY_NmQ 提取码: ky7t 复制这段内容后打开百度网盘手机App,操作更方便哦 需要 to ...

  9. Ubuntu下搭建Kubernetes集群(1)--安装docker

    可以使用物理机,也可以使用虚拟机. 首先参考https://docs.docker.com/install/linux/docker-ce/ubuntu/ 官方文档学会安装docker. 1.首先移除 ...

  10. Meven父工程子模块的SSM框架实现银行转账

            <Meven父工程子模块的SSM框架实现银行转账>                              课程实验报告 实验名称 Meven父工程子模块的SSM框架实现 ...