qml学习文档

一、QML文件的创建

选择qt--->QML File------>选择

二、Window 基础属性

X,Y是以窗口左上角为原点,具体位置是相对于父控件 

x:在窗口中的横向位置

y:在窗口中的纵向位置

width:宽

height:高

visible:可见性

注意:Window需要设置可见性为true,否则不显示窗口

title:标题

opacity: 透明度

minimumHeight:最小高

maximumHeight:最大高

minimumWidth:最小宽

maximumWidth:最大宽

implicitWidth:默认宽度

implicitHeight: 默认高度

radius: 设置圆角

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.5  //qml调用控件需要该头文件
Window {
    width: 500  //宽
    height: 500   //高
    visible: true  //可见性
    title: qsTr("Hello World")  //标题
    //位置
    x:50
    y:50
    opacity: 0.5   //透明度
    minimumHeight: 400  //最小高
    maximumHeight: 400  //最大高
    minimumWidth: 400   //最小宽
    maximumWidth: 600   //最大宽
    implicitWidth:100//默认宽度
    implicitHeight:40// 默认高度
    radius: 10 // 设置圆角
}

三、声明与定义——property

property既可以声明数值类型也可以声明组件类型

property int myTopMar: 0
property int mybotMar: 0
property string mystring: "asd"
property color mycolor: "red"
property url myurl: "qrc:/1.jpg"
property var myvar: value//相当于auto
property Component myComponent

只读:readonly

readonly property int name: value//只读

 必须赋值:required

required property type name: value//必须赋值才能进行

起别名: alias

property alias  newname: oldname

四、矩形——Rectangle

  Rectangle 是一个基本的图形元素,用来绘制矩形。它通常被用作UI组件的背景或作为其它图形元素的容器。

Rectangle {
    width: 100
    height: 50
    color: "blue"//颜色
    border {     //边框
        width: 2
        color: "red"
    }
    radius: 10 // 设置圆角
}

注意:在Rectangel中添加一个子Rectangel时,子控件会显示在父控件之上,子控件也会随着父控件的显示与隐藏来显示与隐藏自己,但popup是个例外

五、组件——Component

       Compon或者开发者封装好的、只暴露必要接口的QML类型ent是Qt框架,可以重复使用。

Component本身并不可见,可以通过添加矩形Rectangle的方式使其变得可见。

Component.onCompleted:{
        console.log("界面创建")//界面创建时触发信号onCompleted
    }
Component.onDestruction: {
        console.log("界面销毁")//界面销毁时调用onDestruction
    }
//自定义Component 
Component {
        id: itemCompont   //设置组件id
        Rectangle {       //矩形
            id: compontRect  //设置矩形id
            color: 'blue'    //设置矩形颜色
            visible:true         //设置能见度可见
            implicitWidth: 200   //默认宽度
            implicitHeight: 50   //默认高度

            Text {               //文本
                id: interText    //设置文本id
                anchors.left: parent.left   //使文本的左边与文本所在父控件的左边对齐
                anchors.leftMargin: 10      //设置左侧锚点的外边距为10个像素单位。
                anchors.verticalCenter: parent.verticalCenter//元素相对于父元素垂直居中
                text: qsTr("text")
            }
            Button {
                anchors.margins: 5  //设置所有锚点的外边距为5个像素单位。
                anchors.top: parent.top //元素的顶部边缘将与父元素的顶部边缘对齐。 
                anchors.bottom: parent.bottom//元素的底部边缘将与父元素的底部边缘对齐。
                anchors.right: parent.right //元素的右边缘将与父元素的右边缘对齐。
                text: '删除'

            }
        }
    }
//调用component,使其生效
Loader{//Component无法自己加载需要通过loader加载
       id:load
        // source: "/MyRectangel.qml"
       sourceComponent: itemCompont  //加载Component 
        //status状态
       onStatusChanged: {
           console.log("status",status)//staus默认为1
       }
    }

Button{
        id:btn
        width: 50
        height: 50
        x:100
        y:100
        onClicked: {
            //load.sourceComponent=null
            load.item.width=100//在component直接用矩形的id改变属性是不可用的,需要使用item调用
            load.item.height=100
        }
    }

Component有两个比较重要的信号

  • Completed:该信号会在界面创建时发出
  • Destruction:该信号会在界面销毁时发出

Component在使用时无法自己加载需要通过Loader加载

六、加载——Loader

装载资源与组件

 Loader{//Component无法自己加载需要通过loader加载
       id:load
       source: "/MyRectangel.qml" //资源地址
       sourceComponent: itemCompont//组件ID
       onStatusChanged: {
           console.log("status",status)//staus默认为1
       }
    }

6.1、状态-status

Loader有四种状态分别为

  • Loader.Null——非活动状态或未设置QML源时的状态——0
  • Loader.Ready——就绪,QML源已加载——1
  • Loader.Loading——加载,QML源当前正在加载——2
  • Loader.Error——错误,QML源加载时出现错误——3

6.2、属性

1、item

使用Loader加载后如果想要调整组件的属性可以用item

load.item.width=100

2、asynchronous

异步操作,当加载大型资源时可以使用asynchronous

asynchronous: true

6.3、加载图片

 //图片
    Component
    {
        id:com
        Image {//静态图
            id: tp1
            source: "/3.gif"
            width:200
            height:200
        }
        AnimatedImage{//动态图
            id:aim
            source: "/3.gif"
            speed: 2//动态的速度
        }
    }
    Loader{
        id:load
        sourceComponent: com
    }
    Button{
        width: 50
        height: 50
        x:200
        onClicked: {
           load.item.paused = !load.item.paused//动态取反,暂停
        }
    }

注:所有控件都可以用过component封装,然后通过loader动态加载

七、鼠标——MouseArea

 MouseArea{
        id:mousearea
        width:200
        height: 200
        enabled: true
        Rectangle{
            anchors.fill: parent//填充并匹配其父元素的大小和位置
            color: "blue"
        }
        Rectangle{
            width:200
            height: 200
            color: "yellow"
            MouseArea
            {
                anchors.fill: parent
                onClicked:
                {
                    console.log("yellow")
                }
            }
            Rectangle{
                width: 100
                height: 100
                color: "red"
                MouseArea{
                    anchors.fill: parent
                    propagateComposedEvents: true//当设置为true时,它允许一个组件处理事件后 
                                                  //继续将该事件传播给其他组件
                    onClicked: {
                        console.log("red")
                        mouse.accepted=false//在鼠标事件处理函数中使用,用来指示该事件没有被 
                                //完全处理,并且应该继续传播给可能对处理此事件感兴趣的其他项目
                    }
                }
            }

       }

        pressAndHoldInterval: 3000//设置长按触发时间
        onPressAndHold: {//长按默认800ms
            console.log("onPressAndHold")
        }

        acceptedButtons: Qt.LeftButton|Qt.RightButton//鼠标左键右键

        onClicked: {//点击
            console.log("clieck")
        }
        onPressed: {//按下
            var ret=pressedButtons&Qt.LeftButton
            var ret2=pressedButtons&Qt.RightButton
            console.log(ret?"left":ret2?"right":"other")
            console.log("pressed")
        }
        onReleased: {//松开
            console.log("reless")
        }
        hoverEnabled: true//鼠标悬停
        onHoveredChanged: {
            console.log("onHoveredChanged")
        }

        onContainsMouseChanged: {//用于判断鼠标是否在元素范围内
            console.log("onContainsMouseChanged")
        }

        onContainsPressChanged: {//用于判断当前元素是否正在被鼠标按压
            console.log("onContainsPressChanged")
        }
        onMouseXChanged: {
            console.log("x:",mouseX)
        }
        onMouseYChanged: {
            console.log("y",mouseY)
        }

        cursorShape://改变光标
            Qt.CrossCursor

   }

7.1、常用信号

  • Clieck:点击
onClicked: {//点击
            console.log("clieck")
        }
  • Pressed:按下
 onPressed: {//按下
            console.log("pressed")
        }
  • Released:松开
onReleased: {//松开
            console.log("reless")
        }

7.2、属性

1、acceptedButtons:此属性包含鼠标区域对其作出反应的鼠标按钮。

acceptedButtons: Qt.LeftButton|Qt.RightButton

2、containsMouse与containsPress:用于判断当前鼠标在不在范围内

如果hoverEnabled为false则只有按下才会触发containsMouse

 onContainsMouseChanged: {
            console.log("onContainsMouseChanged",containsMouse)
        }

        onContainsPressChanged: {
            console.log("onContainsPressChanged",containsPress)
        }

3、hoverEnabled:用于启用鼠标悬停事件的处理。

默认为false

hoverEnabled: true

4、cursorShape:控制光标样式

cursorShape: Qt.CrossCursor

5、Drag:实现鼠标控制拖拽

Rectangle{
        width: 1000
        height: 1000
        id :rec
        color: "green"
        Rectangle{
            id:rect
            width: 50
            height: 50
            color: "red"
            opacity: (600-rect.x)/600//不透明度
            MouseArea{
                anchors.fill: parent
                drag.target: rect//设置在哪里拖动
                drag.axis:Drag.XAxis|Drag.YAxis//控制在X轴移动还是Y轴移动
                drag.minimumX: 0//最小移动位置
                drag.maximumX: rec.width-rect.width//最大移动位置
            }
        }
    }

filterChildren:如果为true,则子控件的MouseArea依然有效但子控件同样继承了父控件的拖动事件

   Rectangle {
        width: 480
        height: 320
        Rectangle {
            x: 30; y: 30
            width: 300; height: 240
            color: "lightsteelblue"

            MouseArea {
                anchors.fill: parent
                drag.target: parent;
                drag.axis: "XAxis"
                drag.minimumX: 30
                drag.maximumX: 150
                drag.filterChildren: true

                Rectangle {
                    color: "yellow"
                    x: 50; y : 50
                    width: 100; height: 100
                    MouseArea {
                        anchors.fill: parent
                        onClicked: console.log("Clicked")
                    }
                }
            }
        }
    }

6、enabled:当前MouseArea是否是使能的,默认true

enabled:false

7、mouseX与mouseY:获取鼠标位置

如果hoverEnabled为true,光标悬停依然触发

        onMouseXChanged: {
            console.log("x:",mouseX)
        }
        onMouseYChanged: {
            console.log("y",mouseY)
        }

8、pressAndHoldInterval:设置长按触发时间

pressAndHoldInterval: 3000//设置长按触发时间

9、propagateComposedEvents :允许复合事件在被一个元素处理后继续传播给其他元素

 Rectangle {
        color: "yellow"
        width: 100; height: 100

        MouseArea {
            anchors.fill: parent
            onClicked: console.log("clicked yellow")
        }

        Rectangle {
            color: "blue"
            width: 50; height: 50

            MouseArea {
                anchors.fill: parent
                propagateComposedEvents: true
                onClicked: {
                    console.log("clicked blue")
                    mouse.accepted = false
                }
            }
        }
    }

八、按钮——Button

Button{
        id:btn
        width: 50
        height: 50
        autoExclusive: true //实现按钮互斥
        checkable: true

    }
    Button{
        id:btn1
        x:60
        width: 50
        height: 50
        autoExclusive: true
        checkable: true

    }
    Button{
        id:btn2
        x:120
        width: 50
        height: 50
        autoExclusive: true
        checkable: true

    }
    Button{
        id:btn
        x:120
        width: 50
        height: 50
        autoRepeat: true//不断触发信号
        autoRepeatDelay: 3000 //第一次按下到信号发生的时间
        autoRepeatInterval: 1000//不断的触发信号的间隔
        onDownChanged: {//如果鼠标按下便为true,如果松开或移开则为false
            console.log("down",down,"press",pressed)
        }

        onClicked:
        {
            console.log("clicked")
        }
        onPressed: {
            console.log("pressed")
        }
        onReleased: {
            console.log("release")
        }
        icon.source: "/1.jpg"
        icon.color: "red"
        indicator: Image {
            id: im
            source: "/1.jpg"
        }
        text: "1234"//文本
        background: Rectangle{
            anchors.fill: btn
            color: {
                if(btn.pressed)
                {
                    return "green"
                }
                else
                {
                    return "blue"
                }
            }
            border.width: 5//边框
            border.color: {
                if(btn.pressed)
                {
                    return "red"
                }
                else
                {
                    return "black"
                }
            }
        }

    }

8.1、属性

1、flat:不绘制背景色,点击显示

flat:true

2、highlighted:背景颜色置为黑色,按下后变为灰色

highlighted: true

3、checkable:使得一些UI元素具有可选中和不可选中的状态。

如果checked状态设为true则checkable会被强制设为true

Button{
        id:btn
        width: 50
        height: 50
        checkable: true
    }

4、autoExclusive:实现互斥

 Button{
        id:btn
        width: 50
        height: 50
        autoExclusive: true //实现按钮互斥
        checkable: true

    }
    Button{
        id:btn1
        x:60
        width: 50
        height: 50
        autoExclusive: true
        checkable: true

    }

5、autoRepeat:不断触发信号

autoRepeat: true//不断触发信号

6、autoRepeatInterval:第一次按下到信号发生的时间

autoRepeatDelay: 3000 //第一次按下到信号发生的时间

7、autoRepeatInterval:不断的触发信号的间隔

autoRepeatInterval: 1000//不断的触发信号的间隔

8、down:如果鼠标按下便为true,如果松开或移开则为false

 onDownChanged: {//如果鼠标按下便为true,如果松开或移开则为false
            console.log("down",down,"press",pressed)
        }

9、icon:用于给用户界面元素(如按钮、菜单项等)添加图标

icon.source: "/1.jpg"//加载路径
icon.color: "red" //修改颜色

10、indicator:用于指代一个视觉元素

indicator: Image { //
            id: im
            source: "/1.jpg"
        }

11、text:文本

 text: "1234"//文本

12、background:用于指定一个控件的背景元素

Button{
        id:btn
        x:120
        width: 50
        height: 50
        background: Rectangle{
            anchors.fill: btn
            color: {
                if(btn.pressed)
                {
                    return "green"
                }
                else
                {
                    return "blue"
                }
            }
            border.width: 5//边框
            border.color: {
                if(btn.pressed)
                {
                    return "red"
                }
                else
                {
                    return "black"
                }
            }
        }
}

 8.2、自定义按钮

由于普通按钮无法满足需求所以需要进行按钮自定义

  • background重绘
Button{
        id:btn
        width: 50
        height: 50
        background: Rectangle{
            anchors.fill: parent
            color: btn.checked|btn.down?"blue":"black"
        }
  •  contentItem对内容做重绘

例:想要文本

contentItem: Text {
            text: btn.text
            font.pixelSize: 18//字体大小
            font.bold: true//粗体
        }

例:想要图片

//文本+图片
text: qsTr("button")
contentItem: Rectangle{
            Text {
                id: text
                text: btn.text
                font.pixelSize: 18//字体大小
                font.bold: true//粗体

            }
            Image {
                id: img
                source: "/1.jpg"
                width: btn.width
                height: btn.height
                anchors.right: btn.right
            }
        }

九、复选框——chekBox

    ButtonGroup{
        id:childbutton
        exclusive: true
        //互斥方法1
      //  buttons: col.children
    }
    Column{
        id:col
        CheckBox{
            checked: true
            text: qsTr("文本1")
            //互斥方法2
            ButtonGroup.group: childbutton

        }
        CheckBox{
            checked: true
            text: qsTr("文本2")
            ButtonGroup.group: childbutton
        }
        CheckBox{
            checked: true
            text: qsTr("文本3")
            ButtonGroup.group: childbutton
        }
    }
    CheckBox{
        checked: true
        nextCheckState: function(){
            if(checkState==Qt.Unchecked)
            {
                return Qt.Checked
            }
            else if(checkState==Qt.Checked)
            {
                return Qt.PartiallyChecked
            }
            else
            {
                return Qt.Unchecked
            }
        }

    }

9.1、属性

1、tristate:控制checkBox是否具有三态

三态:

  • unchecked:未选中
  • partiallyChecked:部分选中
  • checked:选中
CheckBox{
            checked: true
            tristate:true
            text: qsTr("文本1")

        }

2、checkState

  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
        }
    }

 3、nextCheckState: function():回调函数

CheckBox{
        checked: true
        nextCheckState: function(){
            if(checkState===Qt.Unchecked)
            {
                return Qt.Checked
            }
            else if(checkState===Qt.Checked)
            {
                return Qt.PartiallyChecked
            }
            else
            {
                return Qt.Unchecked
            }
        }

    }

9.2、互斥

方法一:

ButtonGroup{
        id:childbutton
        exclusive: true
        buttons: col.children
    }
    Column{
        id:col
        CheckBox{
            checked: true
            text: qsTr("文本1")
        }
        CheckBox{
            checked: true
            text: qsTr("文本2")
        }
        CheckBox{
            checked: true
            text: qsTr("文本3")
        }
    }

方法二:

ButtonGroup{
        id:childbutton
        exclusive: true
    }
    Column{
        id:col
        CheckBox{
            checked: true
            text: qsTr("文本1")
            ButtonGroup.group: childbutton
        }
        CheckBox{
            checked: true
            text: qsTr("文本2")
            ButtonGroup.group: childbutton
        }
        CheckBox{
            checked: true
            text: qsTr("文本3")
            ButtonGroup.group: childbutton
        }
    }

十、按下后进度条——DelayButton

DelayButton{
        width: 100
        height: 50
        delay: 3000//设置时间
        onPressedChanged: {
            console.log(progress)//当前进度
        }
    }

设置时间:delay

delay: 3000//设置时间

十一、单选按钮——RadioButton

  Column {
        RadioButton {
            checked: true
            text: qsTr("First")
        }
        RadioButton {
            text: qsTr("Second")
        }
        RadioButton {
            text: qsTr("Third")
        }
    }

十二、开关——Switch

Column{
        Switch{
            text: "1"
            LayoutMirroring.enabled: true//翻转
            onPositionChanged: {
                console.log("pos",position)//从右往左数
            }
            onVisualPositionChanged: {
                console.log("vis",visualPosition)//从左往右
            }
        }
        Switch
        {
            text: "2"
        }
    }

互斥:

ButtonGroup{
        id:btg
        exclusive: true
        buttons: col.children
    }

    Column{
        id:col
        Switch{
            text: "1"
            LayoutMirroring.enabled: true//翻转
            onPositionChanged: {
                console.log("pos",position)//从右往左数
            }
            onVisualPositionChanged: {
                console.log("vis",visualPosition)//从左往右
            }
        }
        Switch
        {
            text: "2"
        }
    }

12.1、属性

1、Position:从右向左的进度

onPositionChanged: {
                console.log("pos",position)//从右往左数
            }

2、VisualPosition:从左往右的进度

onVisualPositionChanged: {
                console.log("vis",visualPosition)//从左往右
            }

十三、标签按钮——TabButton

   TabBar{
        TabButton{
            text: qsTr("1")
        }
        TabButton{
            text: qsTr("2")
        }
        TabButton{
            text: qsTr("3")
        }
    }

十四、圆形按钮——RoundButton

RoundButton{
        text: "111"
    }

十五、组合按钮——ToolButton

ToolBar {
        Row {
            anchors.fill: parent
            ToolButton {
                text: qsTr("‹")
                onClicked: stack.pop()//回收
            }
            Label {
                text: "Title"
                elide: Label.ElideRight//当label中的内容超出范围时变为省略号
                horizontalAlignment: Qt.AlignHCenter//水平居中对齐
                verticalAlignment: Qt.AlignVCenter//垂直居中对齐
            }
            ToolButton {
                text: qsTr("⋮")
                onClicked: menu.open()//展开
            }
        }
    }

elide:指定了文本内容超出可显示区域时,文本应如何被省略

Label.ElideRight:当label中的内容超出范围时右侧被剪切并且在后面添加省略号

horizontalAlignment: 控制文本在水平方向上的对齐位置

verticalAlignment: 控制文本在垂直方向上的对齐位置

Qt.AlignHCenter:水平方向上居中对齐

Qt.AlignVCenter:垂直居中对齐

十六、文本——text

16.1属性

1、color:设置文本颜色

 Text {
     color: "#00FF00"
     text: "green text"
 }

2、contentHeight:文本高度

Text {
        id: txt
        text: qsTr("text")
        Component.onCompleted: {
            console.log(contentHeight)
        }
    }

3、contentWidth:文本宽度

 Text {
        id: txt
        text: qsTr("text")
        Component.onCompleted: {
            console.log(contentWidth)
        }
    }

4、elide:省略

Rectangle{
        width: 50
        height: 50
        anchors.centerIn: parent
        border.color: "black"
        Text {
            id: txt
            width: 50
            text: qsTr("2222222222222222222222")
            anchors.fill: parent
            elide: Text.ElideRight//只显示一部分文本,后续加省略号来使得文本不会越过父控件的范围
        }
    }

5、font

font.bold: true//粗体
font.family: "courier New"//字体
font.italic: true//斜体
font.letterSpacing: 20//字体之间的距离
font.pixelSize: 36//字体像素为单位
font.pointSize: 36//字体磅为单位
font.underline: true//下划线

6、lineCount:当前文本行数

Component.onCompleted: {
            console.log(lineCount)//lineCount当前文本行数

        }

7、lineHeight:文本间隔高度

lineHeight:1.5
Component.onCompleted: {
            console.log(lineHeight)//lineHeight文本间隔高度

        }

8、textFormat:文本格式

Column{
            Text {
                font.pointSize: 24
                text: "<b>Hello</b> <i>world!</i>"//html
            }
            Text {
                font.pointSize: 24
                textFormat:Text.RichText//富文本形式
                text: "<b>Hello</b> <i>world!</i>"
            }
            Text {
                font.pointSize: 24
                textFormat:Text.PlainText//纯文本
                text: "<b>Hello</b> <i>world!</i>"
            }
            Text {
                font.pointSize: 24
                textFormat:Text.MarkdownText//Markdown语法**加粗*斜体
                text: "**Hello** *world*"
            }
        }

9、wrapMode:换行

WordWrap:通过单词换行

 Rectangle{
        id:rect
        width: 150
        height:150
        border.color: "black"//边框
        Text {
            id: txt
            text: qsTr("text text text texttext text text text")
            anchors.fill: parent
            wrapMode: Text.WordWrap//通过单词判断当每行填满后换行输出
            elide: Text.ElideRight
        }
}

10、超链接

Text{
            text: "See the <a href=\"http://qt-project.org\">Qt Project wedsite</a>."
            onLinkActivated:{
                console.log(link+" link activated")
            }
            onLinkHovered: {
                console.log("hover",link)
            }
            onHoveredLinkChanged: {
                console.log("hover link changed",hoveredLink)
            }
        }
    }

LinkActivated信号:在点击超链接时触发

LinkHovered信号:在鼠标移到超链接上时触发,从超链接上一开始也触发

HoveredLinkChanged信号:在鼠标移到超链接上时触发

手指针样式:

cursorShape: Qt.PointingHandCursor

MouseArea{
          anchors.fill: parent
          hoverEnabled: true
          cursorShape: Qt.PointingHandCursor
          onClicked: {
             Qt.openUrlExternally("http://qt-project.org")
       }
 }

十七、弹出窗口——popup

popup默认visible为false

popup的打开或关闭:

1、手动设置visible属性为true

2、通过open()或者close()

17.1、pupup的两个例外

1、qml中子控件是否显示都受到父控件的影响,但popup是个例外

 Rectangle{
        width: 200
        height: 200
        color: "red"
        visible:false
        Rectangle{
            width: 150
            height: 150
            color: "black"
            visible: true
        }
        Popup{
            width: 50
            height: 50
            visible: true

        }
    }

2、popup的z顺序是一个例外,popup的z顺序只影响其他popup,而对于其他控件popup的z轴优先级最高,在z轴最上层

 Rectangle{
        width: 200
        height: 200
        color: "red"
    }
    Rectangle{
        width: 100
        height: 100
        color: "blue"
    }
    Popup{
        width: 50
        height: 50
        visible: true
        z:-1
        background: Rectangle{
            color: "black"
        }

    }
    Popup{
        width: 20
        height: 20
        visible: true
        z:1
        background: Rectangle{
            color: "white"
        }
    }

17.2、属性

1、closePolicy:关闭策略

默认带两个关闭策略:Popup.CloseOnEscape与Popup.CloseOnPressOutside点击外部与点击esc

不关闭可以使用Popup.NoAutoClose此时只能通过close进行关闭或将属性设置为隐藏

closePolicy: Popup.CloseOnEscape|Popup.CloseOnPressOutside
closePolicy: Popup.NoAutoClose

2、modal模态对话框

模态对话框:只有关闭当前对话框才能进行其他界面的操作

非模态对话框:不关闭当前对话框也可以对其他界面进行操作

modal:true//打开模态对话框
modal:false//打开非模态对话框

3、dim:控制除popup以外的背景颜色

如果是模态对话框则默认为深灰色,如果为非模态对话框则默认不显示,如果dim设置为true则可以看到背景色为浅灰色

dim:true

4、enter:设置打开逻辑

enter: Transition {
        NumberAnimation{
            property: "opacity"
            from:0.0
            to:1.0
            duration: 1000
        }
    }

5、exit:设置关闭逻辑

exit:Transition {
        NumberAnimation{
            property:"opacity"//不透明度
            from: 1.0
            to:0.0
            duration: 1000//1s

        }

6、contentItem:popup的绘制

可根据想要的效果进行定制

contentItem: Rectangle{
        anchors.fill: parent
        Text {
            id: txt
            text: qsTr("Message Box area!!!")
            font.pixelSize: 26
            wrapMode: Text.WordWrap
        }
        Button{
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 30
            anchors.right: parent.right
            anchors.rightMargin: 30
            text: "ok"
        }
        Button{
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 30
            anchors.right: parent.right
            anchors.rightMargin: 230
            text: "close"
        }
    }

7、Overlay:附加属性

Overlay.modal:对应模态对话对话框

Overlay.modal: Rectangle{
        anchors.fill: parent
        color: "blue"
    }

控制除模态对话框以外区域的背景色为蓝色

Overlay.modeless:对应非模态对话框

Overlay.modalless: Rectangle{
        anchors.fill: parent
        color: "blue"
    }

控制除非模态对话框以外区域的背景色为蓝色

设置颜色

Overlay.modeless: Rectangle{
        anchors.fill: parent
        color: "red" //英语设置
        color: "#FF0000"//十六进制
        color: "#33000000"  //RGBA
}

十八、重复组件——Repeater,ListView

18.1、属性

1、model:

如果是数字,表示有几个模型

Repeater{
        //循环几次
        model: 3//模型 数字的话表示有几个模型/控件
        Button{
            y:index*50
            width:100;height:40
        }

 如果是数组形式,则表示可以通过modelData获取model中的数据

Repeater{
        model: ["Button","Rectangel","MouseArea"]
        Button{
            y:index*50
            width:100;height:40
            text: modelData
        }

 listmodel:

     Repeater{
            id:rep
            model: ListModel{

            }
            Button{
                width: 100
                height:50
                text: name
            }
        }

 将listmodel置为空,可以使用insert向listmodel中添加项,实现动态添加

    Button{
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.bottomMargin: 20
        onClicked: {
            rep.model.insert(0,{"name":rep.model.count})
        }
    }

insert第一个参数为要添加的位置,第二个参数为listmodel需要的ListElement的类型

2、index:表示当前是第几个模型

3、count:表示总共有多少模型

4、delegate:控制每一项数据是如何绘制的

ListView{
    width:180;height:200
    model:3 //数字   控制了所有的数据
    //model: ["Button","Rectangel","MouseArea"]
    
    spacing:10//间隔
    delegate: Button{//控制每一项数据是如何绘制的
        text:modelData
    }
}

4、ListModel:封装元素给delegate使用

model: ListModel{
        ListElement{//list元素
            name:"Bill Smith"
            number:"555 3246"
            myvalue:222
        }
        ListElement{
            name:"john brown"
            number:"555 8426"
            myvalue:222
        }
        ListElement{
            name:"sam wise"
            number:"555 0475"
            myvalue:222
        }
    }
    spacing:10//间隔
    delegate: Button{//控制每一项数据是如何绘制的
        text:name+number+myvalue
    }

5、highlight:高亮显示

model: ListModel{
        ListElement{//list元素
            name:"Bill Smith"
            number:"555 3246"
            myvalue:222
        }
        ListElement{
            name:"john brown"
            number:"555 8426"
            myvalue:222
        }
        ListElement{
            name:"sam wise"
            number:"555 0475"
            myvalue:222
        }
    }
    spacing:10//间隔

    highlight: Rectangle{
        color: "lightblue"
        radius: 5
    }


    delegate:Rectangle{
        color: "transparent"//默认白色需要改为透明
        width:list.width
        height:50
        Text {
            id: txt
            text: name
        }
        MouseArea{
            anchors.fill: parent
            onClicked:{
                currentIndex=index
            }
        }
    }

6、currentIndex:保存了当前项的值

7、flickableDirection:滑动回弹效果

默认是Flickable.AutoFlickDirection

  • Flickable.HorizontalFlick——允许水平轻弹
  • Flickable.VerticalFlick——允许垂直轻弹
  • Flickable.HorizontalAndVerticalFlick——允许在两个方向上轻弹
  • Flickable.AutoFlickDirection——如果contentHeight不等于Flickable的高度,则允许垂直轻弹。如果contentWidth不等于Flickable的宽度,则允许水平轻弹。
  • Flickable.AutoFlickIfNeeded——如果contentHeight大于Flickable的高度,则允许垂直轻弹。如果contentWidth大于Flickable的宽度,则允许水平轻弹。
flickableDirection:Flickable.horizontalFilck

8、header与footer

如果想要在listview的上方与下方添加元素但不能影响listview时可以使用header与footer

Rectangle{

    width: 300
    height:200
    border.color: "black"
ListView{
    id:list
    width:180;height:200
    //model:3 //数字   控制了所有的数据
    //model: ["Button","Rectangel","MouseArea"]
    y:20

    model: ListModel{
        ListElement{//list元素
            name:"Bill Smith"
            number:"555 3246"
            myvalue:222
        }
        ListElement{
            name:"john brown"
            number:"555 8426"
            myvalue:222
        }
        ListElement{
            name:"sam wise"
            number:"555 0475"
            myvalue:222
        }
    }
    spacing:5//间隔
    flickableDirection:Flickable.horizontalFilck
    // delegate: Button{//控制每一项数据是如何绘制的
    //     text:name+number+myvalue
    // }
    highlight: Rectangle{
        color: "lightblue"
        radius: 5
    }


    delegate:Rectangle{
        color: "transparent"//默认白色需要改为透明
        width:list.width
        height:50
        Text {
            id: txt
            text: name
        }
        MouseArea{
            anchors.fill: parent
            onClicked:{
                currentIndex=index
            }
        }
    }

    header: Rectangle{
        width: 300
        height:20
        color: "red"
    }

    footer:Rectangle{
        width: 300
        height:20
        color: "blue"
    }
}
}

9、section:排列

Rectangle{

    width: 300
    height:200
    border.color: "black"
    Component {
           id: sectionHeading
           Rectangle {
               width: container.width
               height: childrenRect.height
               color: "lightsteelblue"

               required property string section

               Text {
                   text: parent.section
                   font.bold: true
                   font.pixelSize: 20
               }
           }
      }
ListView{
    id:list
    width:180;height:200
    //model:3 //数字   控制了所有的数据
    //model: ["Button","Rectangel","MouseArea"]
    y:20

    model: ListModel{
        ListElement{//list元素
            name:"Bill Smith"
            number:"555 3246"
            myvalue:1
        }
        ListElement{
            name:"john brown"
            number:"555 8426"
            myvalue:2
        }
        ListElement{
            name:"sam wise"
            number:"555 0475"
            myvalue:3
        }
    }
    spacing:5//间隔
    flickableDirection:Flickable.horizontalFilck
    // delegate: Button{//控制每一项数据是如何绘制的
    //     text:name+number+myvalue
    // }
    highlight: Rectangle{
        color: "lightblue"
        radius: 5
    }


    delegate:Rectangle{
        color: "transparent"//默认白色需要改为透明
        width:list.width
        height:50
        Text {
            id: txt
            text: name
        }
        MouseArea{
            anchors.fill: parent
            onClicked:{
                currentIndex=index
            }
        }
    }
    section.property: "myvalue"//根据哪个属性进行排列
    section.criteria: ViewSection.FullString//FullString完整显示
                                            //FirstCharacter只显示第一个字符
    section.delegate: sectionHeading//控制每一个每一个标题行如何数值
}
}
  • property: 根据哪个属性进行排列
  • criteria:设置标题怎么显示

            ViewSection.FullString完整显示

            ViewSection.FirstCharacter只显示第一个字符

  • delegate:控制每一个每一个标题行如何绘制

 18.2、如何访问复杂组件的子控件

复杂组件内部控件的id是不能直接访问的

  • Repeater

1、可以通过item的索引获取

 Repeater{
        id:rep
        model:3
        Button{
            id:dtn
            y:index*60
            text: "button"+index
        }
    }

    Button{
        id:bt2
        x:200
        text:"click"
        onClicked: {
            for(var i=0;i<rep.count;i++)
            {
                console.log(rep.itemAt(i).text)
            }
        }
    }

2、在布局当中可以直接通过子项的id来访问子项的属性

Column{
        id:col
        Button{
            id:btn
            text:"btn"
        }
        Text {
            id: txt
            text: qsTr("text")
        }
        Rectangle{
            id:rec
            width: 50
            height: 50
            color: "black"
        }
    }
    Button{
        id:btn2
        x:100
        onClicked: {
            console.log(btn.text,txt.text,rec.height)
        }
    }

 3、通过children+ instanceof +控件类型来访问子项

   Column{
        id:col
        Repeater{
            id:rep
            model:3
            Button{
                id:dtn
                text: "button"+index
            }
        }
        Text {
            id: txt
            text: qsTr("text")
        }
        Rectangle{
            id:rec
            width: 50
            height: 50
            color: "black"
        }
    }
    Button{
        id:btn2
        x:100
        text:"bt2"
        onClicked: {
            //console.log(btn.text,txt.text,rec.height)
            for(var i=0;i<col.children.length;i++)
            {
                if(col.children[i] instanceof Button)
                {
                    console.log(col.children[i].text)
                }
            }
        }
    }
  • ListView
ListView{
        id:list
        width: 100
        height: 300
        model: ["zhangsan","lisi","wangwu"]
        delegate: Column{//绘制显示单个项
            Text{
                id:txt
                text: modelData+"text"
            }
            Button{
                id:btn
                text: modelData+"btn"
            }

        }
    }

    Button{
        id:btn2
        x:100
        text:"bt2"
        onClicked: {
            for(var i=0;i<list.contentItem.children.length;i++)
            {
                var col=list.contentItem.children[i]
                for(var j=0;j<col.children.length;j++)
                {
                    console.log(col.children[j])
                }
            }

        }
    }

当listview中delegate的是布局,那整个结构将会非常复杂,需要通过contentItem先获取listview的全部项,子项如果是布局将需要再通过children获取相应的子项

十九、下拉菜单——combobox

19.1、属性

1、model

如果是数字,表示有几个选项,如果是数组,则选项为数组内容

ComboBox{
    model: 3
    //model: ['asd','asf','qwer']
}

2、count:model的长度,表示有几个选项

3、editable:使当前控件可编辑

默认为false

editable: true

4、editText:当前文本

text:editText

5、currentText与currentValue:当前文本与值

onCurrentTextChanged: {
        console.log("text",currentText)
    }
    onCurrentValueChanged: {
        console.log("value",currentValue)
    }

6、textRole与ValueRole:

对应了当前currentText与currentValue的值,可以手动对其进行修改

ComboBox{
    textRole: "value"
    valueRole: "name"
    model: [
        {value:100,text:qsTr("No modifier"),name:"zhangsan"},
        {value:200,text:qsTr("Shift"),name:"lisi"},
        {value:300,text:qsTr("Control"),name:"wangwu"}
    ]

}

 7、displayText

控制combobox最上面显示的文本

displayText: currentText+" "+currentValue

8、validator:控制当前输入的上下限

top:控制当前输入上限

bottom:控制当前输入的下限

ComboBox{
    model:10
    editable: true
    validator: IntValidator{
        top: 20
        bottom: 0
        //regExp:/[0-9A-F]+[.][0-9]/
    }
    onAcceptableInputChanged: {
        console.log(acceptableInput)
    }

19.2、信号

1、Accepted:

按下回车键后触发

ComboBox{
    editable: true
    model: ListModel{
        id:model
        ListElement{
            text:"111"
        }
        ListElement{
            text:"222"
        }
        ListElement{
            text:"333"
        }
    }
    onAccepted: {
        if(find(editText)===-1)
        {
            model.append({text:editText})
        }
    }
}

2、CurrentTextChanged与CurrentValueChanged

onCurrentTextChanged: {
        console.log("text",currentText)
    }
    onCurrentValueChanged: {
        console.log("value",currentValue)
    }

3、acceptableInput

超出上下限会返回false,未超出返回true

onAcceptableInputChanged: {
        console.log(acceptableInput)
    }

19.3、补充

19.3.1、滑动窗体——SwipeView

可以添加多个页面,实现滑动效果

 SwipeView {
        id: view

        currentIndex: 1
        anchors.fill: parent

        Item {
            id: firstPage
            Rectangle{
                anchors.fill: parent
                color: "blue"
            }
        }
        Item {
            id: secondPage
            Rectangle{
                anchors.fill: parent
                color: "red"
            }
        }
        Item {
            id: thirdPage
            Rectangle{
                anchors.fill: parent
                color: "green"
            }
        }
    }

 注意:SwipeView存在缺陷,如果不使用anchors.fill: parent填满父控件,那SwipeView便不可使用。为了解决该问题,可以使用lastView与ObjectModel实现该功能。

19.3.2、ObjectModel:

ObjectModel{
        id:mymode
        Rectangle{
            width:400
            height:500
            color: "blue"
        }
        Rectangle{
            width:400
            height:500
            color: "red"
        }
        Rectangle{
            width:400
            height:500
            color: "green"
        }
    }

    ListView{
        anchors.left: btn.right
        anchors.right: parent.right
        height:500
        model:mymode
        orientation: ListView.Horizontal
        snapMode: ListView.SnapOneItem
        clip: true
        //clip: false
    }

    Button{
        id:btn
        width: 200
        height: 500
    }

头文件:

 import QtQml.Models 2.15

objectmodel默认是上下滑动

如果想要左右滑动可以使用

orientation: ListView.Horizontal

如果想要一次性滑动一个控件可以使用snapMode

snapMode: ListView.SnapOneItem

 如果当子控件超出父控件,是否显示可以使用clip设置

clip: true//超出不绘制
clip: false//超出绘制

 19.3.3、XmlListModel

1、创建一个xml文件

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
    ...
    <channel>
        <item>
            <title>A blog post</title>
            <pubDate>Sat, 07 Sep 2010 10:00:01 GMT</pubDate>
        </item>
        <item>
            <title>Another blog post</title>
            <pubDate>Sat, 07 Sep 2010 15:35:01 GMT</pubDate>
        </item>
    </channel>
</rss>

 头文件

import QtQuick.XmlListModel 2.0


    XmlListModel {
        id: xmlModel
        source: "/myXml.xml"//文件地址
        query: "/rss/channel/item"//xml节点地址

        XmlRole { //类似于listEmelents
            name: "title";
            query: "title/string()" }
        XmlRole { name: "pubDate"; query: "pubDate/string()" }
    }
    ListView{
        width:200
        height: 500
        model: xmlModel
        delegate: Text {
            text: title+":"+pubDate
        }
    }

 19.3.4、FolderListModel

用于管理文件夹

头文件

mport Qt.labs.folderlistmodel 2.15
ListView {
        width: 200; height: 400

        FolderListModel {//能够检查某一路径下的文件
            id: folderModel
            nameFilters: ["*qml"]
            folder: "file:///D:\\360\\qml"//直接设置文件夹地址时前面必须加上file:///
            showDirs: false//默认为true,默认输出文件夹

        }

        //数据与绘制
        model: folderModel//model负责数据
        delegate: Text{//delegate负责绘制
        text: fileName
        }

    }
19.3.4.1属性

1、caseSensitive:是否匹配大小写

2、count:输出个数

3、folder:设置想要看哪一个文件夹下的文件,注意直接设置文件夹地址时前面必须加上file:///

4、showDirs: false//默认为true,默认输出显示文件夹,并且nameFilters无法guolv

5、nameFilters:过滤

6、parentFolder:显示父文件

7、showDirsFirst:先显示文件夹

8、showFiles:默认显示文件,如果改为false就只显示文件夹

9、showHidden:显示隐藏文件

10、showOnlyReadable:显示只读文件

11、sortCaseSensitive:根据大小写排序

19.4自定义combobox

ComboBox {
    id: control
    model: ["First", "Second", "Third"] // 数据模型,定义了下拉列表中的选项

    // 自定义每一个下拉项的外观和行为
    delegate: ItemDelegate { // 针对model中每一项的具体绘制
        width: control.width // 委托项的宽度与ComboBox的宽度一致
        contentItem: Text {
            text: modelData // 显示模型数据(即选项文本)
            color: "red" // 文本颜色设置为红色
            font: control.font // 使用ComboBox的字体设置
            elide: Text.ElideRight // 文本过长时在右侧显示省略号
            verticalAlignment: Text.AlignVCenter // 文本垂直居中对齐
        }
        highlighted: control.highlightedIndex === index // 如果当前项被高亮,则为true
    }

    // 定义ComboBox控件主体的内容
    contentItem: Text {
        leftPadding: 0 // 设置元素内部内容相对于其左边界的内边距
        rightPadding: control.indicator.width + control.spacing // 设置元素内部内容相对于其右边界的内边距,留出空间给指示器
        text: control.displayText // 显示当前选中的文本
        font: control.font // 字体使用ComboBox的设置
        color: control.pressed ? "#17a81a" : "#21be2b" // 根据是否被按下改变文本颜色
        verticalAlignment: Text.AlignVCenter // 垂直居中对齐文本
        elide: Text.ElideRight // 文本过长时在右侧显示省略号
    }

    // ComboBox背景设置
    background: Rectangle {
        implicitWidth: 120 // 默认宽度
        implicitHeight: 40 // 默认高度
        border.color: control.pressed ? "#17a81a" : "#21be2b" // 根据是否被按下改变边框颜色
        border.width: control.visualFocus ? 2 : 1 // 当ComboBox获得视觉焦点时边框宽度加粗
        radius: 2 // 边框圆角半径
    }

    // 定义弹出的下拉列表
    popup: Popup { // 与delegate的区别在于,delegate绘制单个项,而popup绘制整个下拉列表
        y: control.height - 1 // 下拉列表的位置,紧贴ComboBox底部
        width: control.width // 下拉列表的宽度与ComboBox一致
        implicitHeight: contentItem.implicitHeight // 高度根据内容自动调整
        padding: 1 // 内边距

        contentItem: ListView {
            clip: true // 裁剪超出ListView边界的内容
            implicitHeight: contentHeight // 高度根据内容自动调整
            model: control.popup.visible ? control.delegateModel : null // 只有当popup可见时才设置模型
            currentIndex: control.highlightedIndex // 设置当前高亮的项

            interactive: true // 允许通过鼠标进行交互
            boundsBehavior: Flickable.StopAtBounds // 拖动到边界时停止
            ScrollBar.vertical: ScrollBar { // 垂直滚动条
                policy: ScrollBar.AlwaysOn // 滚动条始终显示
            }
        }

        background: Rectangle {
            border.color: "#21be2b" // 边框颜色
            radius: 2 // 边框圆角半径
            layer.enabled: true // 启用图层效果,以显示阴影
            layer.effect: DropShadow{//设置下拉列表中的阴影效果
                horizontalOffset: 2
                verticalOffset: 3//控制纵向偏移
                radius: 8.0      //模糊效果
                samples: 17      //控制具体点的绘制数量
                color: "#80000000"
            }
        }
    }
}

二十、焦点——focus

20.1、FocusScope

      在QML中是一个非常有用的组件,它定义了一个焦点区域,可以控制键盘焦点在其内部的子元素之间如何传递

作用:

  1. 焦点管理:FocusScope允许你创建一个界面区域,在该区域内部,焦点可以自由移动,但不会移出到其他焦点区域。这对于创建模块化UI组件非常有用,每个组件有自己的焦点管理逻辑。

  2. 键盘导航:在使用键盘输入的应用程序中,如桌面应用,FocusScope可以改善用户的键盘导航体验,使用户可以通过键盘如Tab键在特定区域内的元素间切换焦点。

  3. 模态对话框和表单:在模态对话框或表单中,使用FocusScope可以确保用户的焦点仅限于该对话框或表单内的元素,提升用户体验。

注:后构造完成的获取焦点,下方代码构造时先构造rect1再构造rect

FocusScope{
        id:rect
        width: 200
        height: 100
        focus: true

        Button{
            id:btn1
            focusPolicy:"NoFocus"
            anchors.fill: parent
            background: Rectangle{
                anchors.fill: parent
                color: btn1.activeFocus?"red":"blue"

            }
            onClicked: {
                btn1.forceActiveFocus()//获取焦点
            }
        }
    }
    FocusScope{
        id:rect1
        y:200
        width: 200
        height: 100
        Text {
            id: txt1
            focus: true
            text: qsTr("rect2 focus "+txt1.focus+" activeFoucs "+txt1.activeFocus)
        }
        Button{
            id:btn2
            anchors.fill: parent
            focusPolicy:"NoFocus"
            background: Rectangle{
                anchors.fill: parent
                color: btn2.activeFocus?"red":"blue"

            }
            onClicked: {
                btn2.forceActiveFocus()
            }
        }

    }

focus: true:指定一个元素应该获得焦点

通过focus: true可以使得两个不同的控件都能获取焦点,但实际活动焦点activeFocus只有一个在后构造的控件上,可以使用focusPolicy:"NoFocus"设置不获取焦点,当需要获取焦点时可以通过forceActiveFocus()获取

20.2、ActiveFocusItem:

可以通过ActiveFocusItem查看当前获取焦点的控件

onActiveFocusChanged: {
        console.log("activeFocus",activeFocusItem)
    }

二十一、信号与槽

qml端

21.1、自定义信号

//发送信号
    signal testSig(string s,int value)//自定义一个信号
    Button{
        width: 50
        height:50
        onClicked: {
            testSig("zhangsan: ","1")//按钮按下后触发信号
        }
    }
    //接收信号
    //方法1——不常用
    function func(ss,ii){//自定义一个函数
        console.log(ss,ii)
    }
    Component.onCompleted: {
        testSig.connect(func)//func不可以带括号,使用connect调用信号触发后调用的函数
    }
    //方法2——不常用
    Connections{//使用自带的Connections
        target:window
        onTestSig:{//on后面的信号名首字母必须大写
            console.log(s,value)
        }
    }
    //方法3
    Connections{
        target:window
        function onTestSig(str,iValue)//on后面的信号名首字母必须大写
        {
            console.log(str,iValue)
        }
    }

21.2、自定义组件与信号槽的使用

main.qml
Component{
        id:com
        Button{
            id:btn
            background: Rectangle{
                    anchors.fill: parent
                    border.color: btn.activeFocus?"red":"blue"
            }
            signal leftBtnPressed()
            Keys.onLeftPressed: {//键盘左键
                leftBtnPressed()
            }
        }
    }
    MyComponent{//调用新建的qml文件
        com1: com
        com2: com
    }

 创建一个组件,自定义一个信号leftBtnPressed(),当按下键盘左键时触发

MyComponent.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.5

Rectangle{
    width: 400
    height: 300
    property Component com1
    property Component com2
    border.color: "red"
    Loader{
        id:load1
        sourceComponent: com1
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 20
        anchors.right: parent.right
        anchors.rightMargin: 20
        Connections{
            target: load1.item
            ignoreUnknownSignals: true//确保只有信号槽而没有信号时不会报错
            function onLeftBtnPressed(){
                load2.item.focus=true
                load2.item.forceActiveFocus()
            }
        }
        Component.onCompleted: {
            load1.item.focus=true
            load1.item.forceActiveFocus()
        }
    }
    Loader{
        id:load2
        sourceComponent: com2
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 20
        anchors.right: parent.right
        anchors.rightMargin: 150
        Connections{
            target: load2.item
            ignoreUnknownSignals: true
            function onBtnSig(value)
            {
                console.log(value)
            }
            function onLeftBtnPressed(){
                load2.item.focus=true
            }
        }

    }
}

通过connections接受信号,当信号接收后焦点转移

二十二、QML与C++交互

22.1、QML与C++交互基础

MVC设计结构:是一种软件架构模式,旨在分离应用程序的数据层(Model)、用户界面层(View)和业务逻辑层(Controller),以实现关注点分离。这种分离使得应用程序的开发、维护和扩展变得更加容易和高效。MVC模式主要用于Web应用程序和桌面GUI应用程序的开发中。

22.1.1、全局对象——engine

main.cpp
#include <QQmlContext>
#include <QScreen>

    //全局对象,所有qml中都可使用
    QQmlApplicationEngine engine;
    QQmlContext *context=engine.rootContext();
    //获取当前窗口的大小
    QScreen *screen=QGuiApplication::primaryScreen();
    QRect rect=screen->virtualGeometry();
    context->setContextProperty("SCREEN_WIDTH",rect.width());//SCREEN_WIDTH便是值为 
                                                             //rect.width()的全局对象
main.qml
Window {
    id:window
    width: SCREEN_WIDTH  //宽,使用全局变量设置宽度
    height: 500   //高
    visible: true  //可见性
    title: qsTr("Hello World")  //标题
}

22.1.2、QtObject

1、qml:

main.qml

MyRectangel{
        Component.onCompleted: {
            attr.myvalue=200
            console.log("22 "+attr.myvalue)
        }
    }
MyRectangel.qml
Rectangle{
    width: 200
    height:100
    property alias attr:attributes//起别名
    QtObject{//私有化
        id:attributes
        property int myvalue:0
    }
    Component.onCompleted: {
        console.log("11 "+attributes.myvalue)
    }
}

2、自定义一个Object

创建一个继承自QObject的c++类

添加头文件

include <QtQml>

在Q_OBJECT下方添加宏QML_ELEMENT,用于声明为qml可以访问的元素

myqobject.h
class MyQObject : public QObject
{
    Q_OBJECT
    QML_ELEMENT
public:
}

此时可以将需要与qml访问设置的值做定义

例:

myqobject.h

int value;
QString mystring;

定义完成后按下ALT+回车选择第一个

此时将会自动生成一系列用于返回数据的函数并添加了一个宏

myqobject.h

Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged FINAL)
  • int value:定义名
  • READ 设置通过哪个函数读值
  • WRITE 设置通过哪个函数修改值
  • NOTIFY 数值改变时发出信号

通过static创建类的对象

myqobject.h

static MyQObject* getInstance();

myqobject.cpp

MyQObject *MyQObject::getInstance()
{
    static MyQObject *obj=new MyQObject;
    return obj;
}

使用qmlRegisterType方法

main.cpp
 
qmlRegisterType<MyQObject>("MyObj",1,0,"MyQObject");

MyObj:名称

1:主版本号

0:子版本号

MyQObject:模块名

main.qml
import MyObj 1.0

MyQObject{
        id:myobj
        value: 10
        mystring:"aaa";

    }

22.2、QML 端与C++端的信号传输

22.2.1、在qml端直接调用c++端的函数

在函数名前使用宏Q_INVOKABLE

myqobject.h

Q_INVOKABLE void functext();

myqobject.cpp

void MyQObject::functext()
{
    qDebug()<<"111";
}

main.qml

Button{
        onClicked: {
            myobj.functext()
        }
    }

22.2.2、信号与槽

22.2.2.1、qml端发送信号,C++端接收
  • 在qml端绑定
main.qml

signal qmlSig(QVariant i,QVariant s)//在qml端定义信号
    Button{
        onClicked: {
            qmlSig(10,"zhangsan")//按下按钮后发送信号
        }
    }

myqobject.h

public slots:
    void cppSlot(QVariant i,QVariant s);

myqobject.cpp

void MyQObject::cppSlot(QVariant i, QVariant s)
{
    qDebug()<<i<<" "<<s;
}

qml端绑定有两种方法

方法一:

main.qml

Connections{
        target: window
        function onQmlSig(i,s)
        {
            myobj.cppSlot(i,s)
        }
    }

方法二:

main.qml

Component.onCompleted: {
        qmlSig.connect(myobj.cppSlot)
    }
  • 在C++端绑定

1、一定在engin加载完成以后,使用rootObjects返回qml文件的所有对象

main.cpp
#include <QObject>

//engine加载完后,load以后
    auto list=engine.rootObjects();
    auto obname=list.first();
    //通过QObject的connect
    QObject::connect(obname,SIGNAL(qmlSig(QVariant,QVariant))
       ,MyQObject::getInstance(),SLOT(cppSlot(QVariant,QVariant)));

    // auto obname=list.first()->findChild<QObject *>("mybtn");
    // qDebug()<<obname;
22.2.2.2、C++端发送信号,qml端接收

在qml中设置一个函数

main.qml

function qmlSlot(i,s)//参数类型对应CPP端的都是QVariant类型
    {
        console.log("qml ",i,s)
    }

定义一个信号

myqobject.h

void cppSig(int,QString);

链接信号

  • 在qml端绑定
main.qml
Button{
        objectName: "mybtn"
        onClicked: {
            myobj.cppSig(99,"lisi")
        }
    }

Connections{
        target: myobj
        function onCppSig(i,s)
        {
            qmlSlot(i,s)
        }
    }
  •  在C++端绑定

注: 上述代码中的关于myqobject的示例可以不用单独创建,可以使用qmlRegisterSingletonInstance

qmlRegisterSingletonInstance("MyObj",1,0,"MyQObject",MyQObject::getInstance());

后续中可以使用"MyQObject"直接调用c++中的函数而不需要特意声明定义

Button{
        objectName: "mybtn"
        onClicked: {
            MyQObject.functext()//直接使用MyQObject调用函数
        }
    }

//MyQObject{//不需要此步骤
  //      id:myobj
    //}

补充:

在c++端直接调用qml中的函数

在qml文件中定义一个函数

main.qml
function qmlFunc(i , s){
        return "success"
    }

通过QMetaObject::invokeMethod调用

QVariant res;
    QVariant arg1=123;
    QVariant arg2="zhangsan";
    QMetaObject::invokeMethod(obname,//调用的对象
                              "qmlFunc",//调用的函数名称
                              Q_RETURN_ARG(QVariant,res),//通过Q_RETURN_ARG将返回值存在res中
                              Q_ARG(QVariant,arg1),//参数1
                              Q_ARG(QVariant,arg2));//参数二
    qDebug()<<"res="<<res;

二十三、布局——Layout

23.1、纵向——Column

   Column {
        id:col
        spacing: 10
        Repeater{
            id:rep
            model: ListModel{

            }
            Button{
                width: 100
                height:50
                text: name
            }
        }
        add:Transition {
            NumberAnimation{properties: "x,y";easing.type: Easing.OutBounce}
        }
        move:Transition {
            NumberAnimation{properties: "x,y";easing.type: Easing.OutBounce}
        }
        populate:Transition {
            NumberAnimation{properties: "x,y";from:200;duration: 100;easing.type: Easing.OutBounce}
        }
    }
    Button{
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.bottomMargin: 20
        onClicked: {
            rep.model.insert(0,{"name":rep.model.count})
        }
    }

23.1.1、属性

  • add:Transition:用于指定当有新的元素添加到视图或组件中时应该播放的动画
add:Transition {
            NumberAnimation{properties: "x,y";easing.type: Easing.OutBounce}
        }
  • move:Transition:用于定义当元素在视图中移动时的动画效果
move:Transition {
            NumberAnimation{properties: "x,y";easing.type: Easing.OutBounce}
        }
  • populate:Transition:用于定义当一个视图或组件被“填充”时的动画效果。
populate:Transition {
            NumberAnimation{properties: "x,y";from:200;duration: 100;easing.type: Easing.OutBounce}
        }
  • spacing:控件之间的间隔
  • 以下为控制绘制的控件与布局元素(如column)的距离
  • Leftpadding:左
  • bottomPadding:下
  • rightPadding:右
  • topPadding:上

23.2、横向——Row

23.2.1、属性

除effecticeLayoutDirection与layoutDirection外其余与column相同

  • effecticeLayoutDirection:获取layoutDirection控制的方向

0:从左往右

1:从右往左

  • layoutDirection:控制绘制方向
layoutDirection: Qt.RightToLeft//从右往左
layoutDirection: Qt.LeftToRight//从左往右(默认)

23.3、自动换行——Flow

 Rectangle{
        width:200
        height:300
        Flow {
            anchors.fill: parent
            anchors.margins: 4
            spacing: 10

            Text { text: "Text"; font.pixelSize: 40 }
            Text { text: "items"; font.pixelSize: 40 }
            Text { text: "flowing"; font.pixelSize: 40 }
            Text { text: "inside"; font.pixelSize: 40 }
            Text { text: "a"; font.pixelSize: 40 }
            Text { text: "Flow"; font.pixelSize: 40 }
            Text { text: "item"; font.pixelSize: 40 }
        }
    }

23.3.1、属性

属性与前面基本相同,唯一多了flow

  • flow:控制绘制方向
flow: Flow.TopToBottom//从上到下
flow: Flow.LeftToRight//从左往右

二十四、手动控制的行列——Grid

Grid {
        columns: 1//默认值为4
        spacing: 2
        Rectangle { color: "red"; width: 50; height: 50 }
        Rectangle { color: "green"; width: 20; height: 50 }
        Rectangle { color: "blue"; width: 50; height: 20 }
        Rectangle { color: "cyan"; width: 50; height: 50 }
        Rectangle { color: "magenta"; width: 10; height: 10 }
    }

24.1、属性

除了rows与columns,其余与上面相同

  • rows:网格中的行数,如果网格中没有足够的项目来填充指定的行数,则某些行的宽度将为零。
  • columns:网格中的列数,如果网格中没有足够的项目来填充指定数量的列,则某些列的宽度将为零。
 columns: 3
 rows: 5

24.2、自定义Grid与OpacityMask

Grid{
        id:grid
        x:100
        y:100
        width: 15
        height: 200
        columns: 3
        Repeater{
            model:grid.width/5*grid.height/5
            Rectangle{
                width: 5
                height: 5
                color:index%2?"black":"white"
            }
        }
    }

此时如果需要将整体边框设置为圆角直接通过radius会使绘制的所有矩形都为圆角不符合要求,所以需要使用OpacityMask

导入文件

import QtGraphicalEffects 1.15

功能:OpacityMask可以实现按照A的形状添加B的内容

Rectangle{
        id:maskrect
        x:200
        y:100
        width: grid.width
        height:grid.height
        radius: 10
        visible: false
        border.color: "red"

    }
 
OpacityMask{//按照maskrect的形状绘制grid的内容
            source: grid
            maskSource: maskrect
            anchors.fill: maskrect
        }

maskrect只需要它的形状,实际是通过OpacityMask绘制

添加圆角边框可以将OpacityMask放在一个rectangel中

Grid{
        id:grid
        x:100
        y:100
        width: 15
        height: 200
        columns: 3
        visible: false
        Repeater{
            model:grid.width/5*200/5
            Rectangle{
                width: 5
                height: 5
                color:index%2?"black":"white"
            }
        }
    }

    Rectangle{
        id:maskrect
        x:200
        y:100
        width: grid.width
        height:grid.height
        radius: 10
        visible: false
        border.color: "red"

    }

    Button{
        width: 50
        height: 50
        x:50
        y:50
        onClicked: {
            grid.height-=10
        }
    }

    Rectangle{
        width: grid.width+4
        height: grid.height+4
        radius: 10
        border.color: "red"
        border.width: 3
        anchors.bottom: parent.botton
        anchors.horizontalCenter: parent.horizontalCenter
        OpacityMask{
            // width: maskrect.width
            // height: maskrect.height
            source: grid
            maskSource: maskrect
            anchors.fill: parent
            anchors.margins: 2
        }

     }

OpacityMask显示在rectangel上层,而且无法通过z更改顺序,通过调整像素大小可以实现边框显示

二十五、计时器——Timer

 property int time: 0
    Timer{//默认不启动
        id:tim
        interval: 1000//1s
        running: true//启动
        repeat: true//不断触发
        triggeredOnStart: true//使计时器在开始计时时触发一次
        onTriggered: {
            time+=1
        }

    }

    Text {
         id: txt
         text: time
         font.pixelSize: 68//字体大小
         anchors.centerIn: parent//置于屏幕中间
    }
    Button{
        id:btn
        onClicked: {
            // tim.start()//停止计时器
            // tim.stop()//开启计时器,已开启便没有效果
            tim.restart()//重启计时器,假设1秒,当1s没有到达时点击,便重新计时,但已经跑完的不会重置
        }
    }

25.1、属性

1、interval:设置触发间隔

interval: 1000//1s

2、running:启动计时器

默认为fasle,需要手动启动

running: true//启动

3、repeat:设置不断触发计时

默认为fasle

 repeat: true//不断触发

4、triggeredOnStart:使计时器在开始计时时触发一次

默认为true

triggeredOnStart: true//使计时器在开始计时时触发一次

25.2、函数

  • restart

重启计时器,假设1秒,当1s没有到达时点击,便重新计时,但已经跑完的不会重置

tim.restart()
  • start

开启计时器,已开启便没有效果

tim.start()
  • stop

停止计时器

tim.stop()

二十六、自定义Model 

由于repeater、listview、tableview需要设置model但直接使用数字、数组、listmodel一般无法满足动态更改等需求所以需要自定义的Model

新建

这里以listmodel为例

在QAbstractListModel中将virtual QHash<int,QByteArray> roleNames() const;复制出来重写

需要重写这三个函数来实现model的自定义

int MyListModel::rowCount(const QModelIndex &parent) const

作用:返回数据的个数

QHash<int, QByteArray> MyListModel::roleNames() const

int:映射当前需要显示的数据的枚举类型

QByteArray:在qml端使用的名

作用:映射

QVariant MyListModel::data(const QModelIndex &index, int role) const
 

创建实例

MyListModel.h
static MyListModel* getInstance();

MyListModel.cpp
MyListModel *MyListModel::getInstance()
{
    static MyListModel *obj=new MyListModel;
    return obj;
}

定义

MyListView.h
enum MyRoleName{
    Name=Qt::DisplayRole+1,//Qt::DisplayRole为qt默认的枚举
    Value
};


class MyData{
public:
    MyData(QString s,int v):m_string(s),m_value(v){};
    QString m_string;
    int m_value;

};

QList<MyData> m_data

MyListView.cpp
//添加数据
m_data.append(MyData("zhangsan",111));
    m_data.append(MyData("lisi",222));
    m_data.append(MyData("wangwu",333));
    m_data.append(MyData("maliu",444));

创建哈希的类型并 

MyListView.cpp 
  QHash<int, QByteArray> MyListModel::roleNames() const
{
    QHash<int,QByteArray>roles;
    roles.insert(MyRoleName::Name,"name");//字符串是qml端用
    roles.insert(MyRoleName::Value,"value");//枚举是c++端来判断
    return roles;
}

判断

MyListView.cpp
QVariant MyListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if(role==MyRoleName::Name)
    {
        return m_data[index.row()].m_string;
    }
    else if(role==MyRoleName::Value)
    {
        return m_data[index.row()].m_value;
    }
    return QVariant();
}

注册

main.cpp
//在QUrl加载之前
qmlRegisterSingletonInstance("MyModel",1,0,"MyListModel",MyListModel::getInstance());

使用该自定义的model

main.qml
import MyModel 1.0
ListView{
        width: 200
        height: 300
        model: MyListModel
        delegate: Text {
            id: txt
            text: name+" "+value
        }
    }

二十七、图表视图——chartView

导入文件

import QtCharts 2.15

27.1、饼状图——PieSeries

创建图表

例:创建饼状图

Button{
        width: 50
        height: 50
        z:1
        onClicked: {
            var slice=chart.createSeries(ChartView.SeriesTypePie,"mypie")
            slice.append("pie",50)
            slice.append("pi2",100)

        }
    }

 createSeries:创建图表,具有四个参数

参数1:绘制图表类型,如饼状图

参数2:名称

参数3:X坐标系

参数4:Y坐标系 

ChartView {
        id: chart
        title: "Top-5 car brand shares in Finland"
        anchors.fill: parent
        legend.alignment: Qt.AlignBottom
        antialiasing: true//抗锯齿

        PieSeries {
            id: pieSeries
            PieSlice { label: "Volkswagen"; value: 13.5 }
            PieSlice { label: "Toyota"; value: 10.9 }
            PieSlice { label: "Ford"; value: 8.6 }
            PieSlice { label: "Skoda"; value: 8.2 }
            PieSlice { label: "Volvo"; value: 6.8 }
        }
    }

legand:显示图表的图标

antialiasing: 抗锯齿,默认为fasle

PieSeries:绘制饼状图的主控件

PieSlice:绘制的线条

label:默认不显示,可以通过labelVisible设置为true使其显示出来

27.1.1、PieSlice属性

1、angleSpan——当前绘制饼状图所占角度

2、border:边框

borderColor: "red"//颜色
borderWidth: 2//空隙,默认为1

3、exploded:远离当前的饼状图,默认为false

4、explodeDistanceFactor:远离的距离

5、labelArmLengthFactor:控制label距离饼状图的距离

6、labelPosition:控制label在饼状图中的位置,默认为LabelOutside

  • labelPosition: PieSlice.LabelOutside//饼状图外侧
  • labelPosition: PieSlice.LabelInsideHorizontal//横向内置在饼状图中
  • labelPosition: PieSlice.LabelInsideTangential//竖向内置在饼状图中
  • labelPosition: PieSlice.LabelInsideNormal//内置在饼状图中但位置会自动调整

7、startAngel:起始角度,默认为360度,只读
8、value:设置value值,根据value值自动计算比例,总和占比是100%,如果不额外设置,总和的角度为360度 

27.1.2、PieSeries属性

1、count:饼状图中PieSlice的个数

2、size:放缩,默认为0.7倍

3、startAngel:设置起始位置

4、endAngel:设置结束位置

5、horizontalPosition:饼状图的具体位置,默认是0.5

6、sum:整个图表的value值的总和

7、append:添加图表,有两个参数

参数1:label

参数2:value值

Button{
        width: 50
        height: 50
        z:1
        onClicked: {
            var slice=pieSeries.append("mySlice",50)
            slice.labelVisible=true
            slice.borderColor="blue"
        }
    }

8、at:访问某个PieSlice

pieSeries.at(0).exploded=true

9、clear:清空

27.2、折线图——LineSeries

动态创建折线图

property  var linePoints: [[0,0,10,10,20,20,30,30,40,40,50,50],[0,0,10,40,20,25,40,50,50,10]]
    Button{
        width: 50
        height: 50
        z:1
        onClicked: {
            for(var j=0;j<linePoints.length;j++)
            {
                var line=chart.createSeries(ChartView.SeriesTypeLine,"mypline",xAxis,yAxis)
                var points=linePoints[j]
                for(var i=0;i<points.length;i+=2)
                {
                    line.append(points[i],points[i+1])
                }
            }


        }
    }
    ChartView {
        id: chart
        title: "Line"
        anchors.fill: parent
        antialiasing: true
        ValueAxis{
            id: xAxis
            min:0
            max:50
        }
        ValueAxis{
            id: yAxis
            min:0
            max:50
            minorTickCount: 5//间隔虚线数量

        }

    }

在LineSeries中append的两个参数分别为X轴坐标点的位置与y轴坐标点的位置

ValueAxis:用于设置横轴与纵轴的长度 

注意:可以通过ChartView.SeriesTypeSpline绘制曲线,数据添加方法与折线图一致

27.2.1、属性

1、count:点的数量

2、width:线条的宽度

3、style:风格

line.style=Qt.DotLine

27.3、填充型图表——AreaSeries

 ChartView {
        id:chartview
        title: "Line"
        anchors.fill: parent
        antialiasing: true

        LineSeries {
            id:line1
            color: "blue"
            name: "LineSeries"
            XYPoint { x: 0; y: 0 }
            XYPoint { x: 1.1; y: 2.1 }
            XYPoint { x: 1.9; y: 3.3 }
            XYPoint { x: 2.1; y: 2.1 }
            XYPoint { x: 2.9; y: 4.9 }
            XYPoint { x: 3.4; y: 3.0 }
            XYPoint { x: 4.1; y: 3.3 }
        }
        LineSeries {
            id:line2
            color: "red"
            name: "LineSeries"
            XYPoint { x: 0; y: 0 }
            XYPoint { x: 1.1; y: 1.1 }
            XYPoint { x: 1.9; y: 2.3 }
            XYPoint { x: 2.1; y: 1.1 }
            XYPoint { x: 2.9; y: 3.9 }
            XYPoint { x: 3.4; y: 2.0 }
            XYPoint { x: 4.1; y: 2.3 }
        }
    }

    Component.onCompleted: {
        var area=chartview.createSeries(ChartView.SeriesTypeArea,"seri")
        area.upperSeries=line1//上限
        area.lowerSeries=line2//下限
        area.opacity=0.3
        area.color="yellow"

    }

ChartView.SeriesTypeArea:绘制填充型图表

注意上下限并不是严格意义上的上下限,而是指定两个线条,AreaSeries会在两个线条之间进行填充

27.4、柱形图——BarSeries

Component.onCompleted:  {
        var barseries=chartview.createSeries(ChartView.SeriesTypeBar,"myBar",barX,barY)
        barseries.append("mybar",[0,0.1,0.2,0.3,0.4,0.5])
    }

    ChartView {
        id:chartview
        title: "Bar series"
        anchors.fill: parent
        legend.alignment: Qt.AlignBottom
        antialiasing: true

        BarCategoryAxis{
            id:barX
            categories: ["2007", "2008", "2009", "2010", "2011" ]
        }
        ValueAxis{
            id:barY
            min: 0
            max: 2
        }
}

ChartView.SeriesTypeBar:用与绘制柱形图

二十八、动画效果Glow与发射器Emitter

28.1、 Glow

头文件

 import QtGraphicalEffects 1.15
   color: "grey"
    Text {
        id: txt
        text: qsTr("Watting")
        font.pixelSize: 70
        anchors.centerIn: parent
    }

    Glow {
        id:glow
        anchors.fill: txt
        radius: 10
        samples: 17
        color: "white"
        source: txt//设置要执行动画的资源
        SequentialAnimation{//队列的动画效果
            running: true//运行动画
            loops: Animation.Infinite//无限运行动画
            NumberAnimation{
                target: glow
                property: "spread"
                to:0
                duration: 1000//持续时间1s
            }
            NumberAnimation{
                target: glow
                property: "spread"
                to:0.5
                duration: 1000
            }
        }
    }

上述代码可以看到字体外围闪动效果

28.2、Emitter

头文件

 import QtQuick.Particles 2.15
ParticleSystem{//粒子效果的系统
        id:part

    }

    Emitter{//发射器,需要指定系统
        id:emit
        anchors.centerIn: parent
        width: 300
        height: 300
        system: part//指定系统
        emitRate: 10//发射粒子的速度
        lifeSpan: 600//发射粒子的生命周期
        lifeSpanVariation: 400//每个粒子的间隔时间
        size: 60//大小
        velocity: PointDirection{//控制粒子移动的方向
            x:45

        }
    }

    ImageParticle{
        id:img
        source: "/1.jpeg"
        system: part
        color: Qt.rgba(153/255,217/255,234/255,1.0)
        colorVariation: 0.3//根据color随机修改颜色
    }

Attractor:控制当前特效的控件

ParticleSystem{//粒子效果的系统
        id:part

    }

    Emitter{//发射器,需要指定系统
        id:emit
        anchors.centerIn: parent
        width: 300
        height: 300
        system: part//指定系统
        emitRate: 10//发射粒子的速度
        lifeSpan: 600//发射粒子的生命周期
        lifeSpanVariation: 400//每个粒子的间隔时间
        size: 60//大小
        velocity: PointDirection{//控制粒子移动的方向
            x:45

        }
    }

    ImageParticle{
        id:img
        source: "/1.jpeg"
        system: part
        color: Qt.rgba(153/255,217/255,234/255,1.0)
        colorVariation: 0.3//根据color随机修改颜色
    }
    MouseArea{
        id:mouse
        anchors.fill: parent
        hoverEnabled: true
    }

    Attractor{//
        anchors.fill: parent
        enabled: true
        system:part
        pointX: mouse.mouseX
        pointY: mouse.mouseY
        strength: -10000000//粒子被吸引的强度,正值为吸引,负值为排斥
        affectedParameter: Attractor.Position//效果
        proportionalToDistance: Attractor.InverseQuadratic//有弧度的弹飞效果
    }

二十九、Settings

头文件

import Qt.labs.settings 1.0
main.cpp

app.setOrganizationName("myApp");

使用settings需要通过setOrganizationName为QApplication app设置一个名称

Settings{
        id:settings
        //设置配置文件地址
        fileName: "D:\\360\\qml\\setting.ini"
        //注意:不能够使用qml类型,只能用下面的类型
        property int iData: 0
        property double iDouble: 1.23
        property string istring: "my string"
        property var iVar: [1,2,3,4,5,"text"]
        category: "other"//新建分组
    }

    Text {
        id: txt
        text: settings.iData
        font.pixelSize: 40
    }

    Button{
        x:100
        onClicked: {
           // console.log(settings.value("iData",0))//通过value进行值的访问
           settings.setValue("myvalue",4)//添加项与值
        }
    }

fileName:设置配置文件地址

category:新建分组

value:通过value进行值的访问

setValue:项配置文件中添加项与值

三十、states与transitions动画效果制作

30.1、states

类似于switch,可以使用state通过name调用不同的状态

Rectangle{
            id:root
            height: 100
            width: 100
            color: "blue"
            state: "normal"
            states: [
                State {
                    name: "normal"
                    PropertyChanges {
                        target:root;
                        color: "black"}
                },
                State {
                    name: "state1"
                    PropertyChanges {
                    target:root;color: "red";
                    width:200
                    }
                },
                State {
                    name: "state2"
                    PropertyChanges {
                    target:root;color: "blue";
                    height:200
                    }
                }
            ]
            MouseArea {//鼠标
                  anchors.fill:parent
                onPressed: {//鼠标按下
                    root.state="state1"
                }
                onReleased: {//鼠标送开
                    root.state="state2"
                }

            }
     }

30.2、Animation and Transition动画效果

  • 方法一:通过动作手动开启动画
Rectangle{
        id:ant
        width:100
        height: 100
        color: "blue"
        opacity: 1.0//不透明度
        MouseArea{
            anchors.fill: parent
            onClicked: {
                animateColor.start()//start为开启动画
                animateOpacity.start()
                animatewidth.start()
            }
        }
        PropertyAnimation{//属性动画
            id:animateColor
            target: ant
            properties: "color"
            to:"green"
            duration: 1000//持续时间
        }
        NumberAnimation{//数值动画
            id:animateOpacity
            target: ant
            //使透明度从0.1在两秒时间内变成1.0
            properties: "opacity"
            from:0.1
            to:1.0
            duration: 2000
        }
        NumberAnimation{
            id:animatewidth
            target: ant
            properties: "width"
            from:100
            to:200
            duration: 2000
        }
    }

start:开启动画

PropertyAnimation:属性动画

NumberAnimation:数值动画

  • 方法二:通过PropertyAnimation on+属性值,直接修改属性
Rectangle{
        id:rect
        width:100
        height:100

        color: "red"
        
        PropertyAnimation on x{
            to:100
            duration: 1000
        }
        PropertyAnimation on y{
            to:100
            duration: 1000
        }

        //控制颜色
        ColorAnimation on color {
            to: "black"
            duration: 2000
        }
        //队列顺序执行动画
        SequentialAnimation on color {
            ColorAnimation {
                to: "yellow"
                duration: 1000
            }
            ColorAnimation {
                to: "blue"
                duration: 1000
            }

        }
    }

on会导致立即触发动画

SequentialAnimation:可以顺序的执行动画

  • 方法三:通过states与transitions实现过渡动画效果

如果没有transitions,将会直接出现颜色变化,加入transitions后,添加过渡动画效果

Rectangle{
        id:rect
        width: 100
        height: 100
        state: "state1"
        MouseArea{
            anchors.fill: parent
            onPressed: rect.state="state1"
            onReleased: rect.state="state2"
        }

        states: [
            State {
                name: "name"
                PropertyChanges {
                    target: object
                }
            },
            State {
                name: "state1"
                PropertyChanges {
                    target: rect;
                    color:"lightblue"
                }
            },
            State {
                name: "state2"
                PropertyChanges {
                    target: rect;
                    color:"lightsteelblue"
                }
            }
        ]
        transitions: [
            Transition {
                from: "state1"
                to: "state2"

                ColorAnimation {
                    target: rect
                    duration: 2000
                }

            },
            Transition {
                from: "state2"
                to: "state1"

                ColorAnimation {
                    target: rect
                    duration: 2000
                }

            }
        ]
    }
  • 方法四:Behavior行为动画
Rectangle{
        id:rect
        width: 75
        height: 75
        radius:width
        color: "red"
        MouseArea{
            anchors.fill: parent
            acceptedButtons: Qt.LeftButton | Qt.RightButton
                     onClicked: {
                         if (mouse.button == Qt.RightButton)
                         {
                             rect.x +=50;
                             rect.y +=40;
                         }
                         else
                         {
                             rect.x -=50;
                             rect.y -=40;
                         }
                     }
        }

        Behavior on x{
            NumberAnimation{
                id:beha
                easing{
                type:Easing.OutElastic
                amplitude:1.0
                period:0.5
                }
            }
        }
        Behavior on y{
            animation: beha
        }
        Behavior{

            ColorAnimation {
                target: rect
                duration: 200
            }
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值