0
点赞
收藏
分享

微信扫一扫

QML进阶(六)-QML中的常用元素

少_游 2022-05-03 阅读 122

QML是一种用来定义用户交互界面的声明式语言。它将用户交互界面拆分成很多个小的独立单元,通过这些独立单元的组合来构成各种各样的复杂界面。同时通过JavaScript和C++我们可以丰富QML程序的业务逻辑功能。这里有点像HTML+JavaScript,但是区别是QML只是用来描述界面的而不是一个文本文件。

QML属性

在QML文件中,我们通过元素的属性来定义元素的外观,简单的例子如下所示

Text {
        //元素的ID用来查找该元素
        id: labelID

        // 元素的水平位置和垂直位置
        x: 24; y: 16
        //元素的高度是宽度的两倍
        height: 2 * width
        //自定义属性times的值是24
        property int times: 24
        //给属性times起一个别名叫做anotherTimes
        property alias anotherTimes: thisLabel.times
        //给控件添加文本内容并关联自定义属性
        text: "Greetings " + times
        //设置字体类型和字体大小
        font.family: "Ubuntu"
        font.pixelSize: 24
        //Tab扩展关联下一个焦点元素
        KeyNavigation.tab: otherLabel
        //高度变化的时候输出日志
        onHeightChanged: console.log('height:', height)
        //元素获得焦点
        focus: true
        //通过是否获得焦点来修改字体的颜色
        color: focus?"red":"black"
    }

有一点需要注意,QML控件只能引用QML文档内部的元素。虽然QML提供了一种叫做dynamic-scoping的机制,通过该机制我们可以引用之前加载的QML文档中还没有被覆盖的ID,这有点像C++中的全局变量。但是在实际应用中,这个引用依赖于程序文件的加载顺序,很不稳定,所以不建议使用该机制。如果你真的想引用外部元素,最好通过定义根元素属性的方式导出该元素。

JavaScript脚本

我们可以将QML元素和JS脚本写到一起,通过QML元素的变化触发JS脚本的执行:

Text {
        id: label
        x: 24; y: 24
        //定义属性spacePresses
        property int spacePresses: 0

        text: "Space pressed: " + spacePresses + " times"
        //文本变化的时候输出日志
        onTextChanged: console.log("text changed to:", text)
        focus: true
       //空格按下的时候执行JS函数
        Keys.onSpacePressed: {
            increment()
        }
        Keys.onEscapePressed: {
            label.text = ''
        }
        //JS函数
        function increment() {
            spacePresses = spacePresses + 1
        }
    }

基本元素

QML元素可以分为可见元素和不可见元素,可见元素如Rectange有尺寸属性,显示的时候以占据屏幕的一块尺寸。不可见元素如Timer往往提供一种通用功能用来操纵可视化的元素。

Item元素

Item元素是其他可视化元素的根元素,它不可见,但是定义了所有可视化元素的基本属性。

Geometry(尺寸属性)

位置属性(x,y) 尺寸属性(width,height),层次属性(z)

Layout handling(布局属性)

锚定属性(anchor) 间隙属性(margin)

Key handing(按键绑定属性)

按键事件(key\KeyNavigation) 焦点属性(focus)

Transformation(形状变化的属性)

缩放(scale) rotate(旋转) transform/transformOrigin(移动)

Visual(可视化属性)

透明度(opacity) visible(可见性) clip(是否裁剪) smooth(平滑性)

State(状态属性)

通过定义状态和状态间的切换流程,实现各种各样的动画

在QML编程过程中,Item通常会用来做其他元素的容器,有点像HTML中的div 元素.

其他的基本元素

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Basic Elements")

    /**************************矩形元素*******************/
    Rectangle {
        id: rect1
        x: 12; y: 12
        width: 76; height: 96
        //定义背景颜色
        color: "#00FFFF"
    }
    Rectangle {
        id: rect2
        x: 112; y: 12
        width: 76; height: 96
        //定义边框颜色和宽度
        border.color: "#00FFFF"
        border.width: 4
        //定义圆角
        radius: 8
    }

    //通过渐变色来填充矩形
    Rectangle {
        id: rect3
        x: 200; y: 12
        //不设置宽度和高度的话,矩形不可见
        width: 60; height: 60
        gradient: Gradient {
            //定义起点和终点的色值,实现颜色渐变
            //QML不支持有角度的渐变,最好使用预先定义好的图像
            GradientStop { position: 0.0; color: "lightsteelblue" }
            GradientStop { position: 1.0; color: "slategray" }
        }
        border.color: "slategray"
    }

    /**************************Text元素*******************/
    Text {
        //如果没有指定宽度的话,Text的初始宽度依赖于文本和字体
        //如果没有指定文本内容宽度控件不可见,宽度为0
        x:270; y:12
        text: "QML Text Label"
        //背景颜色,字体样式和颜色
        color: "#303030"
        font.family: "Ubuntu"
        font.pixelSize: 20
        width: 240; height: 120

        //文本居中对齐
        elide: Text.ElideMiddle
        //下沉的样式
        style: Text.Sunken
        styleColor: '#FF4444'
        //垂直对齐对齐到顶部
        verticalAlignment: Text.AlignTop
    }

    /**************************图像元素*******************/
    Image {
           x: 12; y: 130
           //图像的地址可以是一个网络地址
           source: "qrc:/transform.png"
           //指定图像的填充模式
           //采用PreserveAspectCrop填充模式,应该将clip开启
           //防止填充超出了控件的范围
           fillMode: Image.PreserveAspectCrop
           clip: true
       }

     /**************************鼠标元素*******************/
    Rectangle {
        id: rect4
        x: 270; y: 130
        width: 76; height: 96
        color: "lightsteelblue"
        MouseArea {
            id: area
            width: parent.width
            height: parent.height
            //点击鼠标区域隐藏矩形
            onClicked: rect4.visible = !rect4.visible
        }
    }
}

显示效果如下图所示:

 

实现自定义控件

QML提供了很多种实现自定义UI元素的方式,最简单的方式就是通过QML文件创建一个基于文件的UI元素.我们定义一个名为MyButton.qml文件用来定义我们自定义的按钮。按钮的文件内容如下:

import QtQuick 2.8
//MyButton.qml
//自定义的UI元素要基于Item
Item
{
    id: root
    width: 116; height: 26
    //导出外部可以访问的元素
    property alias text: label.text
    signal clicked
    //可以鼠标点击的按钮
    Rectangle {
        id: button
        x: 12; y: 12
        width: 116; height: 26
        color: "#4D9CF8"
        border.color: "slategrey"
        Text {
            id:label
            anchors.centerIn: parent
            text: "点击这里"
        }
        MouseArea {
            anchors.fill: parent
            onClicked: {
                status.text = "按钮被点击了"
            }
        }
    }
    //显示需点击的内容
    Text {
        id: status
        x: 12; y: 76
        width: 116; height: 26
        text: "等待中..."
        horizontalAlignment: Text.AlignHCenter
    }
}

定义了可复用的控件元素之后,我们就可以在别的地方调用该UI元素了,调用方法如下:

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Basic Elements")
    MyButton{
        x:30; y:30
        width: 200;height: 400
        text:"测试点击"
    }
}

显示效果如下图所示:

元素姿态变化

姿态变化就是控制元素的UI属性。通常我们可以移动、旋转、缩放一个QML元素,下面以一个例子说明如何控制一个图像元素的几何属性:

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Basic Elements")
    Image {
        id: root
        x:130
        y:100
        width: 50; height: 50
        source: "qrc:/transform.png"
        //开启抗锯齿,提升缩放的时候的图片质量
        antialiasing: true
        MouseArea{
            anchors.fill: parent
            // 每次点击的时候修改图像的旋转角度.尺寸和x坐标          
            onClicked: {
                root.rotation += 15;
                root.scale += 0.1;
                root.x += 5;
            }

        }
    }
}

控制效果如下图所示:

 

 

布局元素

Qt-Widget中有各种布局:水平布局、垂直布局、网格布局,在QML中也有对应的元素,通过各种布局,我们可以按照一定的规律调整元素的位置。除了常见的布局元素之外,QML还有一个比较特殊的流布局(Flow)。该布局将一个元素添加到一个流中,流的方向通过布局方向(layoutDirection)来确定,它可以是从上向下,也可以是从左到右。当元素添加到流布局中之后,它会自动的根据布局的行列数进行调整位置,为了保证流布局的正常工作,我们需要指定布局和宽度和高度。常见布局的用例如下:

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Layout Elements")
    
    //垂直布局
    Column {
        id: column
        x:20; y:20
        //垂直的间隙为8
        spacing: 8
        Rectangle {
            color:"#FF0000";
            width: 48; height: 48
            border.color: Qt.lighter(color)
        }
        Rectangle{
            width: 96
            height: 48
            color: "#00FF00"
            border.color: Qt.lighter(color)
        }
        Rectangle{
            width: 48
            height: 48
            color: "#0000FF"
            border.color: Qt.lighter(color)
        }
    }
    
    //水平布局
    Row {
        id: row
        x:130; y:20
        // 水平的间隙为8
        spacing: 8
        Rectangle {
            color:"#4D9CF8";
            width: 48; height: 48
            border.color: Qt.lighter(color)
        }
        Rectangle{
            width: 48
            height: 48
            color: "#CCCCCC"
            border.color: Qt.lighter(color)
        }
        Rectangle{
            width: 48
            height: 48
            color: "#0D88FF"
            border.color: Qt.lighter(color)
        }
    }
    //网格布局
    Grid {
        id: grid
        rows: 2
        columns: 2
        x:320 ;y:20
        spacing: 10
        Rectangle {
            color:"#4D9CF8";
            width: 48; height: 48
            border.color: Qt.lighter(color)
        }
        Rectangle {
            color:"#4D9CF8";
            width: 48; height: 48
            border.color: Qt.lighter(color)
        }
        Rectangle {
            color:"#4D9CF8";
            width: 48; height: 48
            border.color: Qt.lighter(color)
        }
        Rectangle {
            color:"#4D9CF8";
            width: 48; height: 48
            border.color: Qt.lighter(color)
        }
    }
    //流布局
    Flow {
        x:450 ;y:20
        width: 50
        height: 200
        anchors.margins: 20
        spacing: 20
        layoutDirection: Flow.TopToBottom
        Rectangle {
            color:"#4D9CF8";
            width: 48; height: 48
            Text{
                anchors.fill: parent
                text:"flow"
            }
        }
        Rectangle {
            color:"#4D9CF8";
            width: 48; height: 48
            Text{
                anchors.fill: parent
                text:"flow"
            }
        }
        Rectangle {
            color:"#4D9CF8";
            width: 48; height: 48
            Text{
                anchors.fill: parent
                text:"flow"
            }
        }
    }

}

运行效果如下图所示:

定位元素

QML允许用户使用定位锚的方法来对控件进行布局。锚是QML可视化元素的一种基本属性,通过使用锚我们可以实现元素之间的相对定位。一个元素包括6个主要锚线,分别是:

top、bottom、left、right、horizontalCenter、verticalCenter,如下图所示:

下面介绍一下锚定位的使用方法:

1.元素填充定位

 

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Anchors")
    Rectangle{
        id:rect1
        x:30;y:30
        width: 96
        height: 96
        color: "#4D9CF8"
    }
    Rectangle{
        anchors.fill:rect1
        anchors.margins: 15
        color: "#CCCCCC"
    }
}

 

2.元素左右定位

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Anchors")
    //主矩形
    Rectangle{
        id:rect1
        x:300;y:30
        width: 96
        height: 96
        color: "#4D9CF8"
    }
    //对齐矩形的右边
    Rectangle{
        y: 30
        width: 48
        height: 48
        anchors.left: rect1.right
        anchors.leftMargin: 20
        color: "#CCCCCC"
    }
    //对齐矩形的左边
    Rectangle{
        y: 30
        width: 48
        height: 48
        anchors.right: rect1.left
        anchors.rightMargin:20
        color: "#CCCCCC"
    }
}

对齐效果如下图所示:

 

3.元素上下定位

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Anchors")
    //主矩形
    Rectangle{
        id:rect1
        x:300;y:230
        width: 96
        height: 96
        color: "#4D9CF8"
    }
    //对齐矩形的下边
    Rectangle{
        x:300
        width: 48
        height: 48
        anchors.top: rect1.bottom
        anchors.topMargin:20
        color: "#CCCCCC"
    }
    //对齐矩形的上边
    Rectangle{
        x:300
        width: 48
        height: 48
        anchors.bottom: rect1.top
        anchors.bottomMargin:20
        color: "#CCCCCC"
    }
}

对齐效果如下图所示:

 

 

4.中心对齐

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 20
    height: 280
    title: qsTr("Anchors")
    //主矩形
    Rectangle{
        id: blue1
        width: 48; height: 24
        y: 8
        anchors.horizontalCenter: parent.horizontalCenter
        color:"#4D9CF8"
    }
    Rectangle{
        id: blue2
        width: 72; height: 24
        //对齐blue1的下边,且和blue1水平居中对齐
        anchors.top: blue1.bottom
        anchors.topMargin: 4
        anchors.horizontalCenter: blue1.horizontalCenter
        color:"#00FF00"
    }
    Rectangle{
        //blue3位于blue2的中心
        id: blue3
        width: 30; height: 30
        anchors.centerIn: blue2
        color:"#CCCCCC"
    }
}

对齐效果如下图所示:

5.中心偏移定位

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 320
    height: 480
    title: qsTr("Anchors")
    //主矩形
    Rectangle{
        id: blue1
        width: 100; height: 100
        y: 8
        anchors.horizontalCenter: parent.horizontalCenter
        color:"#4D9CF8"
    }
    Rectangle{
        width: 48
        height: 48
        anchors.horizontalCenter: blue1.horizontalCenter
        anchors.horizontalCenterOffset: -12
        anchors.verticalCenter: blue1.verticalCenter
        color:"#CCCCCC"
    }
}

定位效果如下图所示:

 

输入元素

我们可以使用TextInput元素来实现文本的输入,该元素支持多种输入文本限制策略包括:

validator、inputMask、echMode.下面的例子说明了控件的使用方法:

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 120
    height: 180
    title: qsTr("Anchors")
    Rectangle {
        width: 100
        height: 80
        color: "#4D9CF8"

        TextInput {
            id: input1
            x: 8; y: 8
            width: 96; height: 40
            focus: true
            text: "文本输入1"
            color: "#FFFFFF"
            //支持Tab键在两个控件之间来回切换
            KeyNavigation.tab: input2
        }
        TextInput {
            id: input2
            x: 8; y: 36
            width: 96; height: 40
            text: "文本输入2"
            color: "#FFFFFF"
            KeyNavigation.tab: input1
        }
    }
}

显示效果如下所示:

 

FocusScope元素

使用FocusScope元素作为根元素的时候,如果整个FocusScope元素获得焦点的时候,元素的最后一个包含focus:true属性的元素会接收到对应的焦点。通过这种方法在切换焦点的时候,我们就可以指定复杂控件中的默认焦点元素了。

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Anchors")
    FocusScope {
        x: 0; y:0
        width: 200
        height: 200
        TextInput {
            id: input1
            x:20;y:20
            width: 96
            height: 48
            color: "#4D9CF8"
            anchors.margins: 4
        }
        TextInput {
            id: input2
            y:20
            anchors.left: input1.right
            width: 96
            height: 48
            color: "#4D9C00"
            anchors.margins: 4
            focus: true
        }
        Rectangle {
            id:rectangle
            y:20
            anchors.left: input2.right
            width: 48
            height: 48
            color: "lightsteelblue"
            border.color: "gray"
        }
    }
}

TextEdit元素

TextEdit元素和TextInput元素非常像,主要区别是TextInput是单行的而TextEdit是多行的,并且TextEdit不支持文本限制策略而TextInput支持文本限制策略,这样一来我们就不可以在TextEdit中使用正则表达式等工具限制用户的输入了。用例Demo如下:

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("TextEdit")
    Rectangle {
        width: 136
        height: 120
        color: "linen"

        TextEdit {
            id: input
            x: 8; y: 8
            width: 120; height: 104
            focus: true
            text: "Text Edit"
        }
    }
}

效果如下图所示:

 

按键元素

通过添加按键响应元素,我们可以根据按键响应执行对应的操作,使用用例如下所示:

import QtQuick 2.8
import QtQuick.Window 2.2
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Basic Elements")
    Image {
        id: root
        x:130
        y:100
        width: 50; height: 50
        source: "qrc:/transform.png"
        //通过按键事件我们可以控制图片的位置和尺寸
        antialiasing: true
        focus: true
        Keys.onLeftPressed: root.x -= 8
        Keys.onRightPressed: root.x += 8
        Keys.onUpPressed: root.y -= 8
        Keys.onDownPressed: root.y += 8
        Keys.onPressed: {
            switch(event.key) {
            case Qt.Key_Plus:
                root.scale += 0.2
                break;
            case Qt.Key_Minus:
                root.scale -= 0.2
                break;
            }
        }
    }
}

 

举报

相关推荐

0 条评论