QML重点知识学习
看了以下qgc的源代码,发现里面用到的了很多qml的知识,这是为之前没有接触过的,学习一下。
创建Qt Quick Application —> Qt quick
1. QML之Window
这一部分使用时候一定要注意在文档中(Qt助手)查看属性value的类型
//main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 300
color: "pink"
visible: true
//其他的窗口可以设置为false
title: qsTr("chuanjiujiu")
x:100
y:200
//相对于父控件的位置,window是root控件,其父控件是主界面
maximumHeight: 400
//最大最小窗口
opacity: 0.5
//窗口透明度
//在qml中信号与槽简单化了
signal mySig()//自定义一个信号
onMySig: {
//on+信号名称 触发信号
}
//Window里自带的一些属性也可以被触发
onWidthChanged: {
console.log("width:", width)
}
//可以创建自定义属性
property int myValue: 0
onMyValueChanged: {
}//会自动生成可触发属性
Button{
id: btn1//此时id是为了在qml里可以通过id来访问其他控件
width: 50
height: 50
focus: true
objectName: "btn1"
//string类型
//这里是为了在控制台容易辨别这个按钮 起一个名字 否则在控制台是编号
background: Rectangle{
border.color: btn1.focus ? "blue" : "black"
}
Keys.onRightPressed: {
btn2.focus = true
}
}
Button{
id: btn2//此时id是为了在qml里可以通过id来访问其他控件
x:100
width: 50
height: 50
objectName: "btn2"
background: Rectangle{
border.color: btn2.focus ? "blue" : "black"
}
Keys.onLeftPressed: {
btn1.focus = true
}
}
onActiveFocusItemChanged: {
console.log("active focus item changed", activeFocusItem)
}
//这个是找到丢失的focus 在控制台打印
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cJLJxSAp-1691552214499)(/home/cjj/.config/Typora/typora-user-images/image-20230801150941383.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FheDQjlE-1691552214500)(/home/cjj/.config/Typora/typora-user-images/image-20230801152948154.png)]
2. QML之Rectangle
Rectangle自己的属性不多,不过它继承自Item,可以看Item的属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6pt0WInS-1691552214501)(/home/cjj/.config/Typora/typora-user-images/image-20230801160014849.png)]
Focus的使用
Rectangle {
x:50
y:50
width: 100
height: 100
color: "blue"
focus: true
//activeFocus
MouseArea {
anchors.fill: parent
onClicked: {
console.log("on clicked")
}
}
Keys.onReturnPressed: {
console.log("on return pressed")
}//这个地方要配合focus为true使用 此时控件获取焦点可以检测到回车
}
锚点anchors
控件填充整个父控件fill
Rectangle {
id:rect1
anchors.fill: parent//此时parent是Window
width: 100
height: 50
color: "black"
}
控件布局leftMargin
Rectangle {
id:rect1
width: 100
height: 50
color: "black"
}
Rectangle {
id:rect2
width: 100
height: 50
anchors.left: rect1.right//此时两个矩形在同一行
anchors.leftMargin: 20//两个矩形之间的空隙
anchors.top: rect1.bottom//一列
anchors.centerIn: parent//居中于父控件
anchors.horizontalCenter: parent.horizontalCenter//横向居中
anchors.verticalCenter: parent.verticalCenter//垂直居中
color: "black"
}
让控件旋转rotation
Rectangle {
id:rect1
width: 100
height: 50
color: "black"
rotation: 30//让元素旋转 30度
}
放缩控件scale
Rectangle {
id:rect1
width: 100
height: 50
color: "black"
scale: 2//放大原来的两倍
}
Rectangle自己的属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-21imA0Bi-1691552214501)(/home/cjj/.config/Typora/typora-user-images/image-20230802100504142.png)]
//渐变
Rectangle {
y: 100
width: 80
height: 80
gradient: Gradient {
GradientStop { position: 0.0; color: "lightsteelblue" }
GradientStop { position: 1.0; color: "blue" }
}
}
Rectangle {
y: 200; width: 80; height: 80
rotation: 90
gradient: Gradient {
GradientStop { position: 0.0; color: "lightsteelblue" }
GradientStop { position: 1.0; color: "blue" }
}
}
Rectangle实现自定义边框
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kTnjCNzz-1691552214502)(/home/cjj/.config/Typora/typora-user-images/image-20230802103111006.png)]
//自定义边框
//MyRectangle.qml
Rectangle{
id: borderRect
property int myTopMargin: 0//把属性暴露出去可以外部修改
color: "black"
Rectangle{
id:innerRect
color: "blue"
anchors.fill: parent
anchors.topMargin: 0
anchors.bottomMargin: myTopMargin
anchors.rightMargin: 0
anchors.leftMargin: 0
}
}
//main.qml
//调用MyRectangle
Window {
width: 640
height: 300
color: "pink"
visible: true
//其他的窗口可以设置为false
title: qsTr("chuanjiujiu")
//可以直接调用Rectangle 并修改自定义属性
MyRectangle{
x:100
y:50
width: 200
height: 100
myTopMargin: 10
}
}
3. QML之动画-Item的states/transition
states
Rectangle {
id: root
width: 100; height: 100
state: "red_color"
//此时是通过state而非color修改颜色
//目的是可以比较方便的修改控件当前的状态,比如颜色宽度等
//我自己认为是封装起来可以方便修改属性
states: [
State {
name: "red_color"
PropertyChanges { target: root; color: "red" }
},
State {
name: "blue_color"
PropertyChanges { target: root; color: "blue" }
}
]
}
MouseArea{
anchors.fill: parent
onPressed: {
root.state = 'blue_color'
}//按下鼠标变成蓝色
onReleased: {
root.state = 'red_color'
}//松开鼠标变成红色
}
transitions直接修改使用Start开启动画
Rectangle {
id: flashingblob
width: 75; height: 75
color: "blue"
opacity: 1.0
MouseArea {
anchors.fill: parent
onClicked: {
animateColor.start()//开启动画效果
animateOpacity.start()
}
}
PropertyAnimation {
id: animateColor;
target: flashingblob;
properties: "color";
to: "green";
duration: 1000//持续时间
}
NumberAnimation {
id: animateOpacity
target: flashingblob
properties: "opacity"
from: 0.1
to: 1.0
duration: 2000//持续时间
}
}
**transitions的ProperyAnimation on 属性值 { to: }**使用on开启动画
Rectangle {
id: rect
width: 100; height: 100
color: "red"
PropertyAnimation on x { to: 100 }
PropertyAnimation on y { to: 100 }
//修改当前控件位置
//ProperyAnimation on 属性值 { to: }
//修改属性值
}
还会有其他ColorAnimation on color、SequentialAnimation on color等动画效果
transitions
Rectangle {
width: 75; height: 75
id: button
state: "RELEASED"
MouseArea {
anchors.fill: parent
onPressed: button.state = "PRESSED"
onReleased: button.state = "RELEASED"
}
states: [
State {
name: "PRESSED"
PropertyChanges { target: button; color: "lightblue"}
},
State {
name: "RELEASED"
PropertyChanges { target: button; color: "lightsteelblue"}
}
]
transitions: [//使用transitions从一个状态切换到另一个状态
Transition {
from: "PRESSED"
to: "RELEASED"
ColorAnimation { target: button; duration: 100}
},
Transition {
from: "RELEASED"
to: "PRESSED"
ColorAnimation { target: button; duration: 100}
}
]
}
Behavior
Rectangle {
width: 75; height: 75; radius: width
id: ball
color: "salmon"
MouseArea{
anchors.fill: parent
onClicked: {
ball.x +=50
ball.y +=40
}
}
//点击之后Behavior才会被触发 本例子是bounce弹跳
Behavior on x {
NumberAnimation {
id: bouncebehavior
easing {
type: Easing.OutElastic
amplitude: 1.0
period: 0.5
}
}
}
Behavior on y {
animation: bouncebehavior
}
Behavior {
ColorAnimation { target: ball; duration: 100 }
}
}
4. QML之Component/Loader
Window {
//root控件 父窗口是主界面
width: 640
height: 300
color: "pink"
visible: true
//其他的窗口可以设置为false
title: qsTr("chuanjiujiu")
//此时的Componet是包含root控件的组件
Component.onCompleted: {
console.log('oncom')//界面创建的时候就触发了onCompleted打印了oncom
}
Component.onDestruction: {
//在窗口销毁时调用
}
}
Componet可以理解为root组件,onCompleted会在root控件生成的时候被触发,也就是窗口生成的时候,此时可以打印一些有用的信息。
同时我们也可以自己创建Componet组件,组件内部是我们需要封装的Rectangle控件,和普通控件不同的是,Component需要我们手动加载,也就是用Loader加载。(这里是异步加载的概念)
已经加载的组件修改item
此时可以使用Loader的item属性修改
Component{
id: com
Rectangle{
width: 200
height: 100
color: 'black'
}
}
//使用Loader加载上面的Componet
Loader{
id: loader
sourceComponent: com
onStateChanged: {
}
}
Button{
width: 50
height: 50
x:250
onClicked: {
//此时loader.item就是上面的Componet(com)里的Rectangle
//loader加载的最top-level的控件
loader.item.width=50
loader.item.height=50
loader.item.color='blue'
}
}
Loader的不同状态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EzXR48Q2-1691552214503)(/home/cjj/.config/Typora/typora-user-images/image-20230803102752139.png)]
asynchronous 异步加载此时Loader状态为Loading
Image加载在Component里使用image{}加载静态图片
5. QML之MouseArea
MouseArea默认颜色和背景色一样,所以可以在里面套一个Rectangle
MouseArea{
id:mouseArea
width: 200
height: 200
Rectangle{
anchors.fill: parent
color: 'red'
}
onclicked{
//触发点击后执行
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lKadYfjl-1691552214503)(/home/cjj/.config/Typora/typora-user-images/image-20230803104704898.png)]
acceptedButtons: Qt::MouseButtons支持左键或者右键或者其他
MouseArea{
id:mouseArea
width: 200
height: 200
//左右建都可以触发事件
acceptedButtons: Qt.LeftButton | Qt.RightButton
Rectangle{
anchors.fill: parent
color: 'red'
}
onClicked: {
console.log('click')
}
//pressedButtons这个属性只能在onPressed里用
//Click不可以用因为此时已经释放release
onPressed: {
var ret = pressedButtons & Qt.LeftButton
console.log(ret ? 'left' : 'right')
}
}
drag可以拖动组件详见Qt助手手册
6. QML之Button
Button
Button如果想设置样式要在Button里放上Rectangle来设置。
Button{
id:btn
width: 150
height: 100
Rectangle{
anchors.fill: parent
color: btn.checked | btn.down ? 'blue' : 'black'
//在内部控件中要通过id来调用属性
//btn.checked
}
}
Button扩展
DelayButton
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YrfMIZDx-1691552214503)(/home/cjj/.config/Typora/typora-user-images/image-20230803155048203.png)]
RedioButton
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TSAwPs9B-1691552214504)(/home/cjj/.config/Typora/typora-user-images/image-20230803155140353.png)]
Switch
实现单选都要用ButtonGround
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BPzOUt1d-1691552214504)(/home/cjj/.config/Typora/typora-user-images/image-20230803155248879.png)]
TabBar默认单选
contentItem实现按钮的重绘
Button {
id: control
text: qsTr("Button")
contentItem: Label {
text: control.text
font: control.font//可以调整字体大小
verticalAlignment: Text.AlignVCenter
}
//还可以使用Image放按钮图片
}
7. QML之Property
Property的基本用法是Property int Myid = 3
,基本的变量类型都可使用,包括color、url等。
动态加载组件
//MyRectangle.qml
Rectangle{
id: myrec
width: 200
height: 200
color: "black"
property Component myCom //把属性暴露出去可以外部修改
Rectangle{
id:innerRect
color: "blue"
//加载外面传进来的Component
//这里传入button
Loader{
id:loader
sourceComponent: myCom
}
anchors.fill: parent
anchors.topMargin: 0
anchors.bottomMargin: 10
anchors.rightMargin: 0
anchors.leftMargin: 0
}
}
//main.qml
//外部定义Componet
Component{
id:com
Button{
width: 50
height: 50
}
}
//在MyRectangle里调用
MyRectangle{
myCom: com
}
还有通用类型var类型,可以传入任何类型,list类型,动态创建数组。
希望外部访问不希望被修改(类似getter)
在属性前加上readonly,readonly Property int Myid = 3
必须赋值才能继续的情况(必须setter)
在属性前加上required,required Property int Myid = 3
外部访问子控件
使用property alias newName: oldName
在控件外面写一个别名,这样外部就可以访问到控件里的属性/控件
8. QML之CheckBox
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s1LDJ7Sh-1691552214505)(/home/cjj/.config/Typora/typora-user-images/image-20230803153425267.png)]
包括CheckBox在内的很多控件都继承在AbstractButton
CheckBox效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RkY7AOjw-1691552214506)(/home/cjj/.config/Typora/typora-user-images/image-20230803153605171.png)]
tristate实现三态
单选框实现
//使用ButtonGroup实现
ButtonGroup{
id: childGroup
exclusive: true//排他
buttons: col.children
}
Column {
id: col
CheckBox {
checked: true
text: qsTr("First")
//ButtonGroup.group: childGroup
//第二种方法
}
CheckBox {
text: qsTr("Second")
}
CheckBox {
checked: true
text: qsTr("Third")
}
}
全选功能
Column {
ButtonGroup {
id: childGroup
exclusive: false
checkState: parentBox.checkState
}
CheckBox {
id: parentBox
text: qsTr("Parent")
checkState: childGroup.checkState
}
CheckBox {
checked: true
text: qsTr("Child 1")
leftPadding: indicator.width
ButtonGroup.group: childGroup
}
CheckBox {
text: qsTr("Child 2")
leftPadding: indicator.width
ButtonGroup.group: childGroup
}
}
9. QML之Text
可以设置字体之类的
10. QML之Popup与Oerlay
也就是弹窗
11. QML之Repeater
重复器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Po1YpApj-1691552214506)(/home/cjj/.config/Typora/typora-user-images/image-20230804122845850.png)]
Repeater{
model: 3 //模型 如果是数字的话 表示有几个模型/控件
Rectangle{
y: index*50
width:100
height: 40
border.width: 1
color: 'yellow'
}
}
重复器不仅可以是数字,还可以是数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RISZc11c-1691552214506)(/home/cjj/.config/Typora/typora-user-images/image-20230804123310146.png)]
Repeater{
model: ['no.1','no.2','no.3']
Button{
y: index*50
width:100
height: 40
text: modelData//modelData可以获取model数组的值
}
}
12. QML之ListView
ListView {
width: 180; height: 200
model: 3//控制所有数据
spacing: 10//控制控件之间距离
delegate: Button {//控制每一项数据是如何绘制的
text: index
}
}
13. QML之ComboBox
就是下拉菜单控件,可以参考文档
14. QML之focus-FocusScope
15. QML之信号与槽
自己定义qml端的交互
connect连接
//自己写一个信号
signal testSig(string s, int val)
//处理信号的函数
function func(ss, ii){
console.log(ss, ii)
}
//触发信号
Button{
id:btn
width: 50
height: 50
onClicked: {
testSig('cjj', 22)
}
}
//接收信号并处理
Component.onCompleted: {
testSig.connect(func)
}
使用connection连接更简单
Window {
//root控件 父窗口是主界面
id: window
width: 640
height: 300
color: "pink"
visible: true
//其他的窗口可以设置为false
title: qsTr("chuanjiujiu")
//自己写一个信号
signal testSig(string s, int val)
//触发信号
Button{
id:btn
width: 50
height: 50
onClicked: {
testSig('cjj', 22)
}
}
//接收信号
Connections{
target: window//谁发出信号
onTestSig:{
console.log(s, val)
}
}
//接收信号方法2
// Connections{
// target: window//谁发出信号
// function onTestSig(str, iValue){
// console.log(str, iValue)//此时可以自己指定参数名
// }
// }
}