1.组件介绍

  • 一个组件通常由一个qml文件定义(单独文件定义组件), 实际也可以在qml里面通过Component对象来嵌入式定义组件 (4小节讲解).
  • Component对象封装的内容默认不会显示,除非被加载后才可能显示, 并且是可以重复加载和移除的.
  • Component一般用来封装比较小,且需要重用的组件.

比如我们需要4个自定义按钮,我们只需要按钮颜色不同而已,此时就可以只需要定义一个按钮组件(Component),然后我们重复加载即可.而不是不停复制和粘贴来定义4个不同颜色的椭圆按钮.

2.单独文件定义组件

一个组件通常由一个qml文件定义,那么该文件名就是该组件的名字(类似于java,类名就是文件名).并且文件名最好是大驼峰格式.

由于我们是单独文件定义一个组件,所以不需要Component对象封装,并且创建好,我们就可以像使用qml其它元素一样来使用我们定义的组件.

首先我们创建一个名为DynamicBtn的自定义按钮组件:

DynamicBtn.qml内容如下所示:

import QtQuick 2.7
import QtQuick.Controls 2.0 Button {
id: btn
property var backColor: "#7BCBEB" // 背景颜色
property var fontPixelSize: 20 // 字体大小
property var fontColor: "#FFFFFF" text: "button"
implicitWidth: 100
implicitHeight: 30
hoverEnabled: true
contentItem: Label { // 设置文本
id: btnForeground
text: parent.text
font.family: "Microsoft Yahei"
font.pixelSize: fontPixelSize
color: fontColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle { // 绘制高亮范围
id: btnBack
color: backColor
radius: 6
Rectangle {
width: btnBack.width * 0.9
height: btnBack.height * 0.4
x: btnBack.width * 0.05
y: btnBack.height * 0.05
radius: 3
color: Qt.lighter(btnBack.color, 1.19) }
}
onDownChanged: {
btnBack.color = down ? Qt.lighter(backColor, 0.9) : backColor // 设置按下的背景颜色
}
onHoveredChanged: {
btnBack.color = hovered ? Qt.lighter(backColor, 1.2) : backColor // 设置徘徊的背景颜色
}
}

然后我们在main.qml中就可以直接使用这个DynamicBtn组件了,就像使用qml内置的Window组件那样

main.qml内容如下所示:

Window{
visible: true
function onConfirmBtnClicked() {
console.log("你点击了确认按钮");
}
function onCancelBtnClicked() {
console.log("你点击了取消按钮");
} Column {
spacing: 20
padding: 20
DynamicBtn {
id: confirmBtn
text: "确认"
backColor: "#5CA1F6" }
DynamicBtn {
id: cancelBtn
text: "取消"
backColor: "#FB6E62"
}
Component.onCompleted: {
confirmBtn.clicked.connect(onConfirmBtnClicked)
cancelBtn.clicked.connect(onCancelBtnClicked)
}
}
}

运行效果如下所示:

3.使用Loader对象动态加载和移除

在上节中,我们是在main.qml中直接使用这个DynamicBtn组件来静态显示,如果要动态加载和移除组件的话,则需要使用Loader对象,比如需要延时时间来显示对象之类的,都可以用Loader来实现.

Loader对象的属性如下所示:

  • active : bool,默认为true,表示Loader是激活的,如果设置为false,那么加载的视图项将会被释放,但是不会影响source或 sourceComponent里的内容.
  • asynchronous : bool,此属性保存组件是否将异步实例化,默认为false,在多个帧中创建组件声明的对象时,使用异步加载就可以降低动画中出现故障的可能性
  • item : object,此属性保存当前加载的顶级对象。
  • progress : real,此属性保存从网络加载QML数据的进度,从0.0(未加载)到1.0(完成)。大多数QML文件都很小,因此该值将迅速从0更改为1。
  • source : url,此属性保存要实例化的QML组件的URL。要卸载当前加载的对象,请将此属性设置为空字符串,将source设置为新URL也将导致卸载由先前URL创建的项。
  • sourceComponent : Component,此属性保存要实例化的Component,要卸载当前加载的对象,请将此属性设置为undefined
  • status : enumeration,保存当前加载的状态,分别有
  1. Loader.Null - the loader is inactive or no QML source has been set
  2. Loader.Ready - the QML source has been loaded
  3. Loader.Loading - the QML source is currently being loaded
  4. Loader.Error - an error occurred while loading the QML source

Loader的信号如下所示:

  • loaded() : 当status属性变为Loader.Ready成功加载后,会发出此信号。

我们还是以DynamicBtn组件为例,示例如下所示:

Window{
visible: true function onLoad() {
loader1.source = "qrc:/DynamicBtn.qml"
loader2.source = "qrc:/DynamicBtn.qml"
}
function onRemove() {
loader1.source = ""
loader2.source = ""
}
function onConfirmBtnClicked() {
console.log("你点击了确认按钮");
btnText.text = "你点击了确认按钮"
}
function onCancelBtnClicked() {
console.log("你点击了取消按钮");
btnText.text = "你点击了取消按钮"
} Row {
id: row
spacing: 20
padding: 20
Button {
id: load
text: "加载"
onClicked: onLoad();
}
Button {
id: remove
text: "移除"
onClicked: onRemove();
}
} Column {
anchors.top: row.bottom
spacing: 20
padding: 20
Loader {
id: loader1
onLoaded: {
item.text = "确认"
item.backColor = "#5CA1F6"
item.clicked.connect(onConfirmBtnClicked)
}
}
Loader {
id: loader2
onLoaded: {
item.text = "取消"
item.backColor = "#FB6E62"
item.clicked.connect(onCancelBtnClicked)
}
} Text {
id: btnText
text: "等待按钮点击"
}
}
}

界面运行起来如下所示:

点击加载按钮后如下所示:

点击移除后,那么确认和取消按钮将会消失

4. 使用Component嵌入式定义组件

如果我们不想让自定义的按钮组件单独存在一个独立文件中,而是和main.qml一起的话,则需要用Component对象来封装它,修饰该对象是个组件对象.

并且Component只能包含一个顶层item,在这个item之外除了定义id外,不能定义其它任何属性.

然后我们在Loader的sourceComponent属性填入我们要加载的Component的id,即可加载显示.

Qt帮助示例如下所示:

import QtQuick 2.0

Item {
width: 100; height: 100 Component {
id: redSquare // Component里面只有一个id和一个顶层item,这里的顶层item是一个Rectangle矩形
Rectangle {
color: "red"
width: 10
height: 10
}
}
Loader { sourceComponent: redSquare } // 加载一个矩形
Loader { sourceComponent: redSquare; x: 20 } // 在x为20的位置处再次加载一个矩形
}

我们还是以DynamicBtn组件为例,来实现一个Component,示例如下所示:

import QtQuick 2.14
import QtQuick.Window 2.0
import QtQuick.Controls 2.0 Window{
visible: true function onLoad() {
loader1.sourceComponent = dynamicBtn
loader2.sourceComponent = dynamicBtn
}
function onRemove() {
loader1.source = undefined
loader2.source = undefined
}
function onConfirmBtnClicked() {
console.log("你点击了确认按钮");
btnText.text = "你点击了确认按钮"
}
function onCancelBtnClicked() {
console.log("你点击了取消按钮");
btnText.text = "你点击了取消按钮"
} Row {
id: row
spacing: 20
padding: 20
Button {
id: load
text: "加载"
onClicked: onLoad();
}
Button {
id: remove
text: "移除"
onClicked: onRemove();
} } Column {
anchors.top: row.bottom
spacing: 20
padding: 20
Loader {
id: loader1
onLoaded: {
item.text = "确认"
item.backColor = "#5CA1F6"
item.clicked.connect(onConfirmBtnClicked)
} }
Loader {
id: loader2
onLoaded: {
item.text = "取消"
item.backColor = "#FB6E62"
item.clicked.connect(onCancelBtnClicked)
}
} Text {
id: btnText
text: "等待按钮点击" }
} Component {
id: dynamicBtn
Button {
property var backColor: "#7BCBEB" // 背景颜色
text: "button"
implicitWidth: 100
implicitHeight: 32
hoverEnabled: true
contentItem: Label { // 设置文本
id: btnForeground
text: parent.text
font.family: "Microsoft Yahei"
font.pixelSize: 20
color: "#FFFFFF"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
id: btnBack
color: backColor
radius: height / 4 Rectangle {
width: btnBack.width * 0.9
height: btnBack.height * 0.4
x: btnBack.width * 0.05
y: btnBack.height * 0.05
radius: width / 2
color: Qt.lighter(btnBack.color, 1.09) }
}
onDownChanged: {
btnBack.color = down ? Qt.lighter(backColor, 0.9) : backColor // 设置按下的背景颜色
}
onHoveredChanged: {
btnBack.color = hovered ? Qt.lighter(backColor, 1.1) : backColor // 设置徘徊的背景颜色
}
}
}
}

未完,下章学习组件其它动态创建方式:11.qml-通过方法来加载组件、字符串方式加载组件

10.qml-组件、Loader、Component介绍的更多相关文章

  1. QML之使用Loader加载QML组件

    呵呵,今晚是边看<裸婚时代>边敲代码,那电影看得...!钱真他妈不是个东西. 盼望Meego火起来. QML的Loader元素经常备用来动态加载QML组件.可以使用source属性或者so ...

  2. Qt 学习之路 2(79):QML 组件

    前面我们简单介绍了几种 QML 的基本元素.QML 可以由这些基本元素组合成一个复杂的元素,方便以后我们的重用.这种组合元素就被称为组件.组件就是一种可重用的元素.QML 提供了很多方法来创建组件.不 ...

  3. Qt 学习之路:QML 组件

    前面我们简单介绍了几种 QML 的基本元素.QML 可以由这些基本元素组合成一个复杂的元素,方便以后我们的重用.这种组合元素就被称为组件.组件就是一种可重用的元素.QML 提供了很多方法来创建组件.不 ...

  4. React-Native之轮播组件looped-carousel的介绍与使用

    React-Native之轮播组件looped-carousel的介绍与使用 一,关于react-native轮播组件的介绍与对比 1,react-native-swiper在动态使用网页图片,多张图 ...

  5. C# BackgroundWorker组件学习入门介绍

    C# BackgroundWorker组件学习入门介绍 一个程序中需要进行大量的运算,并且需要在运算过程中支持用户一定的交互,为了获得更好的用户体验,使用BackgroundWorker来完成这一功能 ...

  6. hibernate 组件(Component)映射

    1.类Teacher public class Teacher { private int id; private String name; private String sex; private A ...

  7. qml: 组件复用

    在编写组件时,使用下面两种方法可以实现组件的复用: import QtQuick 2.0 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 a ...

  8. 「小程序JAVA实战」小程序视频组件与api介绍(51)

    转自:https://idig8.com/2018/09/22/xiaochengxujavashizhanxiaochengxushipinzujianyuapijieshao50/ 这次说下,小程 ...

  9. 日志组件Log2Net的介绍和使用(附源码开源地址)

    Log2Net是一个用于收集日志到数据库或文件的组件,支持.NET和.NetCore平台. 此组件自动收集系统的运行日志(服务器运行情况.在线人数等).异常日志.程序员还可以添加自定义日志. 该组件支 ...

随机推荐

  1. Python中类的特殊属性和魔术方法

    1.属性 属性 含义 __name__ 类.函数.方法等的名字   __dir__ __module__ 类定义所在的模块名 __class__ 对象或类所属的类   只是返回基类 __bases__ ...

  2. 浅析MyBatis(二):手写一个自己的MyBatis简单框架

    在上一篇文章中,我们由一个快速案例剖析了 MyBatis 的整体架构与整体运行流程,在本篇文章中笔者会根据 MyBatis 的运行流程手写一个自定义 MyBatis 简单框架,在实践中加深对 MyBa ...

  3. 白话解读 WebRTC 音频 NetEQ 及优化实践

    NetEQ 是 WebRTC 音视频核心技术之一,对于提高 VoIP 质量有明显的效果,本文将从更为宏观的视角,用通俗白话介绍 WebRTC 中音频 NetEQ 的相关概念背景和框架原理,以及相关的优 ...

  4. wrf模拟的domain图绘制

    wrf模拟的区域绘制,domain图,利用python的cartopy库绘制模拟区域 参考Liang Chen的draw_wrf_domian.py这个代码, 出处python画wrf模式的模拟区域 ...

  5. windows回收站无法设置

    win+r运行 regedit HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer 修改NoRe ...

  6. 攻防世界 reverse elrond32

    tinyctf-2014 elrond32 1 int __cdecl main(int a1, char **arg_input) 2 { 3 if ( a1 > 1 && c ...

  7. MyBatis笔记(三)

    1. ResultMap 查询结果为null:要解决属性和字段名不一致的问题 我们先来看下步骤: 数据库中的字段名 Java中的实体类 public class User {    private i ...

  8. [Skill]从零掌握正则表达式

    前言 无论你是出于什么原因需要掌握正则表达式(诸如爬虫.文本检索.后端服务开发或Linux脚本),如果之前从没接触过正则表达式(比如我)很容易在如山般的公式中迷失,以至于你在项目写的正则表达式很可能会 ...

  9. xctf - stack2

    xctf - stack2 文件check一下,几乎全开了 运行一下程序,好像很正常呢: 再来一个大的,好像有点儿问题,变1.00了 在ida中查看,在输入的时候没有检查数据大小 可以通过劫持eip获 ...

  10. ECDSA密钥对生成以及在Token中的应用

    1 概述 本文主要讲述了如何利用Openssl生成ECDSA密钥对,并利用Auth0库进行Token生成及验证的过程. 2 ECDSA 2.1 简介 ECC(Elliptic Curve Crypto ...