使用QML绘制汽车时速表

使用QML绘制仪表

Qt看了一段时间了,一直觉得适宜做仪表等显示界面。对于QML也只是看看网上的代码,不求甚解。现在模仿网友的例子,自己亲手试一试,记录一下过程,也是在这里的第一篇文章。
本文参考 https://blog.csdn.net/t01051/article/details/107518308
Here we go!

新建QML工程

新建一个空的Quick应用。
在这里插入图片描述在这里插入图片描述
完成后,得到一个HelloWorld的空项目。
在这里插入图片描述

添加自定义控件

添加一个.qml文件,用来定义自己的时速表,然后在main.qml中导入使用。

在工程树的多个位置都可使用Add New来添加新的文件,添加的文件会默认放在当前位置下。这里在Resources/qml.qrc/下添加
在这里插入图片描述
在这里插入图片描述

定义控件

这里编写qml文件了。
根据所引文章,首先绘制了两个重叠的圆弧。使用property定义控件的必要属性,并使用onXxxxxxChanged(格式:onChanged)的信号处理器,当某个属性的值变更时,会触发Canvas的重绘(即mycanvas.requestPaint())

//Mymeter.qml
import QtQuick 2.0

Item {
    id: meterItem
    width: 100
    height: 100

    property int btm_lineWidth: 15
    property color btm_bgcolor: Qt.rgba(0,0,0,0.1)
    property int btm_r: 20
    property double btm_startangle: 0
    property double btm_endangle: 90

    onBtm_bgcolorChanged:mycanvas.requestPaint()
    onBtm_endangleChanged: mycanvas.requestPaint()
    onBtm_lineWidthChanged: mycanvas.requestPaint()
    onBtm_rChanged: mycanvas.requestPaint()
    onBtm_startangleChanged: mycanvas.requestPaint()

    property int top_lineWidth: 15
    property color top_bgcolor: "lightgreen"
    property int top_r: 20
    property double top_startangle: 0
    property double top_endangle: 90

    onTop_bgcolorChanged: mycanvas.requestPaint()
    onTop_endangleChanged: mycanvas.requestPaint()
    onTop_lineWidthChanged: mycanvas.requestPaint()
    onTop_startangleChanged: mycanvas.requestPaint()
    onTop_rChanged: mycanvas.requestPaint()

    Canvas{
        id: mycanvas
        width: parent.width
        height: parent.height

        onPaint: {
            var ctx = getContext("2d");
            ctx.clearRect(0,0,mycanvas.width,mycanvas.height);

            ctx.lineWidth = meterItem.btm_lineWidth;
            ctx.strokeStyle = meterItem.btm_bgcolor;
            ctx.beginPath();
            ctx.arc(meterItem.width/2,meterItem.width/2,meterItem.btm_r,meterItem.btm_startangle/180*Math.PI,meterItem.btm_endangle/180*Math.PI);
            ctx.stroke();

            ctx.lineWidth = meterItem.top_lineWidth;
            ctx.strokeStyle = meterItem.top_bgcolor;
            ctx.beginPath();
            ctx.arc(meterItem.width/2,meterItem.width/2,meterItem.top_r,meterItem.top_startangle/180*Math.PI,meterItem.top_endangle/180*Math.PI);
            ctx.stroke();
        }
    }
}

在main.qml中引用自定义的仪表控件

import QtQuick 2.12
import QtQuick.Window 2.12


Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Mymeter{
    }
}

切换到设计界面,自定义的仪表控件已经被载入到界面中,点击导航下方的Mymeter类,右方可以看到其属性,更改自定义属性,可以直接看到更改效果。
在这里插入图片描述
同时,在main.qml中,Mymeter的属性已经更新。

添加刻度盘

在仪表上绘制表盘,首先定义表盘的一些属性,然后进行绘制

    ...
    // 刻度盘
    property color dial_color: "#000000"
    property int dial_lineWidth: 3
    property int dial_addR: 2          // 刻度盘圆弧与底层圆弧的距离
    property int dial_longNum: 5       // 刻度盘长刻度线的数量
    property int dial_longLen: 10      // 刻度盘长刻度线的长度

    onDial_addRChanged: mycanvas.requestPaint()
    onDial_colorChanged: mycanvas.requestPaint()
    onDial_lineWidthChanged: mycanvas.requestPaint()
    onDial_longLenChanged: mycanvas.requestPaint()
    onDial_longNumChanged: mycanvas.requestPaint()
    ...
     Canvas{
		...	
        onPaint: {
            ...
            ctx.lineWidth = meterItem.dial_lineWidth;
            ctx.strokeStyle = meterItem.dial_color;
            ctx.beginPath();
            ctx.arc(meterItem.width/2, meterItem.height/2, meterItem.btm_r+meterItem.btm_lineWidth+meterItem.dial_addR, meterItem.btm_startangle/180*Math.PI, meterItem.btm_endangle/180*Math.PI);
            var tmp_step = (meterItem.btm_endangle-meterItem.btm_startangle)/meterItem.dial_longNum;
            for(var i=meterItem.btm_startangle;i<meterItem.btm_endangle+tmp_step;i+=tmp_step) {
                 var tmp_x = (meterItem.width/2)+(meterItem.btm_r+meterItem.btm_lineWidth+meterItem.dial_addR)*Math.cos(i/180*Math.PI);
                 var tmp_y = (meterItem.height/2)+(meterItem.btm_r+meterItem.btm_lineWidth+meterItem.dial_addR)*Math.sin(i/180*Math.PI);
                 ctx.moveTo(tmp_x, tmp_y);
                 // 绘制长刻度线
                 ctx.lineTo(tmp_x+meterItem.dial_longLen*Math.cos(i/180*Math.PI), tmp_y+(meterItem.dial_longLen*Math.sin(i/180*Math.PI)));
            }
            ctx.stroke();

           ...
        }

添加刻度

直接使用basic控件,设置好位置,文字等。

在这里插入图片描述

添加控件

为仪表盘添加几个控件,一个开关用来控制顶层圆弧的线宽,滑块用来模拟汽车的速度,文本框用来显示速度。。。

在这里插入图片描述
在这里插入图片描述

代码

main.qml完整代码如下

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3


Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Mymeter{
        id: meter_car
        x: 195
        y: 49
        width: 228
        height: 213
        dial_longNum: 10
        top_startangle: 140
        btm_startangle: 140
        btm_r: 80
        top_r: 80
        top_lineWidth: 15
        top_endangle: slider.value*1.3+140
        btm_lineWidth: 13
        btm_endangle: 400

        Text {
            id: element5
            x: 106
            y: -11
            width: 12
            height: 13
            text: qsTr("100")
            font.pixelSize: 12
        }

        Text {
            id: element6
            x: 156
            y: -1
            width: 13
            height: 14
            text: qsTr("120")
            font.pixelSize: 12
        }

        Text {
            id: element7
            x: 194
            y: 28
            width: 12
            height: 14
            text: qsTr("140")
            font.pixelSize: 12
        }

        Text {
            id: element9
            x: 218
            y: 77
            width: 12
            height: 14
            text: qsTr("160")
            font.pixelSize: 12
        }

        Text {
            id: element12
            x: 23
            y: 171
            width: 12
            height: 14
            text: qsTr("0")
            font.pixelSize: 12
        }

        Text {
            id: speed_unit
            x: 102
            y: 112
            width: 22
            height: 13
            text: qsTr("Km/h")
            font.pixelSize: 12
        }

        Text {
            id: speed
            x: 101
            y: 94
            width: 22
            height: 12
            text: slider.value
            font.pixelSize: 15
            horizontalAlignment: Text.AlignHCenter
        }

        Slider {
            id: slider
            x: 12
            y: 218
            stepSize: 1
            to: 200
            value: 0

            onValueChanged: {
               if(value<60) {
                    speed.color = "black"
                }
                else if(value<120) {
                    speed.color = "#f2ac28"
                }
                else {
                    speed.color = "red"
                }
                speed_unit.color = speed.color
            }
        }

        Switch {
            id: swi
            x: 251
            y: -38
            width: 101
            height: 40
            text: qsTr("Switch")
            onClicked: {
            if(swi.position)
                meter_car.top_lineWidth = meter_car.btm_lineWidth*0.6;

            else
                meter_car.top_lineWidth = meter_car.btm_lineWidth;

        }
    }

    Text {
        id: element
        x: 15
        y: 37
        width: 12
        height: 14
        text: qsTr("60")
        font.pixelSize: 12
    }

    Text {
        id: element1
        x: -1
        y: 132
        width: 12
        height: 14
        text: qsTr("20")
        font.pixelSize: 12
    }

    Text {
        id: element2
        x: -5
        y: 82
        width: 12
        height: 14
        text: qsTr("40")
        font.pixelSize: 12
    }

    Text {
        id: element4
        x: 54
        y: 0
        width: 18
        height: 14
        text: qsTr("80")
        font.pixelSize: 12
    }

    Text {
        id: element10
        x: 218
        y: 127
        width: 12
        height: 14
        text: qsTr("180")
        font.pixelSize: 12
    }

    Text {
        id: element11
        x: 199
        y: 171
        width: 12
        height: 14
        text: qsTr("200")
        font.pixelSize: 12
    }
    }
}

后续

后续完善代码,增加C++交互。

引用

引用博客链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值