QML —— 圆形波浪进度条控件(附上源码)
效果
说明
QML中使用画布元素(canvas element),使用画布元素可画出各种各样的图形,同时允许脚本绘制。画布元素提供了一个依赖于分辨率的位图画布,也可以使用JavaScript脚本来绘制图形,制作游戏或者其它的动态图像。QML中的画布元素是基于HTML5的画布元素来完成的。
画布元素的基本思想是使用一个2D对象来渲染路径。这个2D对象包括了必要的绘图函数,画布元素充当绘制的画布。
代码
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.14
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4Window
{visible: truewidth: 500height: 300RowLayout{spacing: 50anchors.verticalCenter: parent.verticalCenterColumnLayout{spacing: 20Row{Text{text: qsTr("设置当前值:");font.pixelSize: 16;anchors.verticalCenter: parent.verticalCenter}SpinBox{font.pixelSize: 16value: 60maximumValue: 100onValueChanged:{wscProgress.setCurrentValue(value)}style: SpinBoxStyle{background: Rectangle{implicitWidth: 100implicitHeight: 20border.color: "gray"radius: 2}}}}Row{Text{text: qsTr("设置波浪宽度:");font.pixelSize: 16;anchors.verticalCenter: parent.verticalCenter}SpinBox{font.pixelSize: 16value: 0.4decimals: 2maximumValue: 1stepSize: 0.05onValueChanged:{wscProgress.setWaveWidth(value)}style: SpinBoxStyle{background: Rectangle{implicitWidth: 100implicitHeight: 20border.color: "gray"radius: 2}}}}Row{Text{text: qsTr("设置波浪高度:");font.pixelSize: 16;anchors.verticalCenter: parent.verticalCenter}SpinBox{font.pixelSize: 16value: 3;maximumValue: 20;stepSize: 1onValueChanged:{wscProgress.setWaveHeight(value)}style: SpinBoxStyle{background: Rectangle{implicitWidth: 100implicitHeight: 20border.color: "gray"radius: 2}}}}Row{Text{text: qsTr("设置波浪速度:");font.pixelSize: 16;anchors.verticalCenter: parent.verticalCenter}SpinBox{font.pixelSize: 16value: 0.09;maximumValue: 2;stepSize: 0.04;decimals: 2onValueChanged:{wscProgress.setWaveSpeed(value)}style: SpinBoxStyle{background: Rectangle{implicitWidth: 100implicitHeight: 20border.color: "gray"radius: 2}}}}Button{id: buttonheight: 24width: 60Layout.alignment: Qt.AlignHCentertext: qsTr("运行-圆波浪形进度条")onClicked:{if (wscProgress.isRun() === false){wscProgress.setRun(true)button.text = qsTr("停止-圆波浪形进度条");}else{wscProgress.setRun(false)button.text = qsTr("运行-圆波浪形进度条");}}}}Rectangle{width: 200height: 200WaveShapedCircularProgressBar{id: wscProgressanchors.centerIn: parent}}}
}
WaveShapedCircularProgressBar.qml
import QtQuick 2.0Item
{/*******************************************************/// 设置是否运行该控件function setRun(runFlag){timer.running = runFlag}// 获取该控件运行状态function isRun(){return timer.running}// 设置当前值(最大100)function setCurrentValue(value){rangeValue = value;}// 设置波浪宽度function setWaveWidth(fValue){waveWidth = fValue}// 设置波浪高度function setWaveHeight(Value){waveHeight = Value}// 设置波浪速度function setWaveSpeed(fValue){speed = fValue}/*******************************************************///range信息property int rangeValue: 60;property int nowRange: 0;//画布property int mW: 250;property int mH: 250;property int lineWidth: 2;//圆property double r: mH / 2; //圆心property double cR: r - 16 * lineWidth; //圆半径//Sin曲线property int sX: 0;property int sY: mH / 2;property int axisLength: mW; //轴长property double waveWidth: 0.25; //波浪宽度,数越小越宽property double waveHeight: 3; //波浪高度,数越大越高property double speed: 0.09; //波浪速度,数越大速度越快property double xOffset: 0; //波浪x偏移量Canvas{id: canvasheight: mHwidth: mWanchors.centerIn: parentonPaint:{var ctx = getContext("2d");ctx.clearRect(0, 0, mW, mH);//显示外圈ctx.beginPath();ctx.strokeStyle = '#148014';ctx.arc(r, r, cR+5, 0, 2*Math.PI);ctx.stroke();ctx.beginPath();ctx.arc(r, r, cR, 0, 2*Math.PI);ctx.clip();//显示sin曲线ctx.save();var points=[];ctx.beginPath();for(var x = sX; x < sX + axisLength; x += 20 / axisLength){var y = -Math.sin((sX + x) * waveWidth + xOffset);var dY = mH * (1 - nowRange / 100 );points.push([x, dY + y * waveHeight]);ctx.lineTo(x, dY + y * waveHeight);}//显示波浪ctx.lineTo(axisLength, mH);ctx.lineTo(sX, mH);ctx.lineTo(points[0][0],points[0][1]);ctx.fillStyle = '#1c86d1';ctx.fill();ctx.restore();//显示百分数ctx.save();var size = 0.4*cR;ctx.font = size + 'px Arial';ctx.textAlign = 'center';ctx.fillStyle = "rgba(14, 80, 14, 0.8)";ctx.fillText(~~nowRange + '%', r, r + size / 2);ctx.restore();//增加Rang值if(nowRange <= rangeValue){nowRange += 1;}if(nowRange > rangeValue){nowRange -= 1;}xOffset += speed;}Timer{id: timerrunning: falserepeat: trueinterval: 50onTriggered:{parent.requestPaint();}}}
}
关注
笔者 - jxd