示例效果]
源码
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
Window
{
id: root
visible: true
width: 800
height: 600
title: qsTr("Hello World")
ColumnLayout
{
anchors.top: parent.top
Layout.topMargin: 10
spacing: 5
RowLayout
{
Layout.alignment:Qt.AlignHCenter
Text
{
text: qsTr("当前时间:")
font.family: "微软雅黑"
font.pixelSize: 20
}
Text
{
id: currentTimeID
text: qsTr("--")
color: "pink"
font.family: "Courier New"
font.pixelSize: 40
font.bold: true
}
}
MyClock
{
Layout.alignment:Qt.AlignHCenter
id:rootClock
onCurrentPaintTime:{currentTimeID.text = timeString}
}
}
}
MyClock.qml
import QtQuick 2.0
import QtQuick.Window 2.12
Item
{
id: rootClock
visible: true
// width: 740
// height: 680
signal currentPaintTime(var timeString)
Timer
{
interval: 980
running: true
repeat: true
onTriggered:{canvasClock.requestPaint()}
}
Canvas
{
id: canvasClock
anchors.fill: parent
onPaint:
{
// 获取绘制2d画笔对象
let painter2D = getContext("2d")
painter2D.clearRect(0,0,width,height)
// 绘制背景相关
drawBackground(painter2D)
// 绘制中心点
drawCenterPoint(painter2D)
// 绘制时分秒
var date = new Date();
var hours = date.getHours()
var minutes = date.getMinutes()
var seconds = date.getSeconds();
drawTime_hour(painter2D,hours%12)
drawTime_minute(painter2D,minutes)
drawTime_second(painter2D,seconds)
// 信号传递出绘制的时间
currentPaintTime(hours+":"+minutes+":"+seconds);
}
}
// 背景圆半径取窗口宽高最小值的某个系数
property int windowMinValue : Math.min(root.width,root.height)
property int backgroundRadius : windowMinValue*0.4
function drawBackground(painter2D)
{
// 保存当前绘制环境
painter2D.save()
// 将当前路径重置为新路径
painter2D.beginPath()
// 变换坐标起始点
painter2D.translate(root.width/2,root.height/2)
// 像素清除为透明黑色
painter2D.clearRect(-backgroundRadius,-backgroundRadius,backgroundRadius*2,backgroundRadius*2)
/******************** 绘制背景圆 ********************/
// 绘制外侧大圆
painter2D.arc(0,0,backgroundRadius,0,360)
painter2D.fillStyle = "#edeef7"
painter2D.fill()
// 使用当前笔划样式笔划子路径
painter2D.stroke()
/**************************************************/
/******************** 写背景文字 ********************/
let backgroundText = [12,1,2,3,4,5,6,7,8,9,10,11]
painter2D.font = "bold " + (windowMinValue/20)+"px \"Courier New\""
painter2D.textAlign = "center"
painter2D.textBaseline = "middle"
painter2D.fillStyle = "black";
for(var indexText=0;indexText<12;++indexText)
{
let rotatoAngle = (indexText * 30) // 30°
let realAngle = 90- rotatoAngle;
let x = Math.floor(backgroundRadius*0.85 * (Math.cos(realAngle*Math.PI/180)))
let y = Math.floor(backgroundRadius*0.85 * (Math.sin(realAngle*Math.PI/180)))
painter2D.fillText(backgroundText[indexText],x,-y) // 文字
}
/**************************************************/
/******************** 画背景刻度 ********************/
for(var indexMark=0;indexMark<60;++indexMark)
{
let rotatoMarkAngle = (indexMark * 6)*Math.PI/180 // 6°
painter2D.save()
painter2D.beginPath()
painter2D.rotate(rotatoMarkAngle) // 旋转
painter2D.moveTo(0,backgroundRadius)
if(indexMark%5==0){painter2D.lineWidth=backgroundRadius*0.03;painter2D.lineTo(0,backgroundRadius*0.95)}
else{painter2D.lineTo(0,backgroundRadius*0.95)}
painter2D.stroke();
painter2D.restore()
}
/**************************************************/
// 释放当前绘制环境
painter2D.restore()
}
function drawCenterPoint(painter2D)
{
painter2D.save()
painter2D.beginPath() // 必须加入
painter2D.translate(root.width/2,root.height/2)
painter2D.arc(0,0,backgroundRadius*0.02,0,360);
painter2D.fillStyle="#000000"; // 填充色
painter2D.fill(); // 进行填充
painter2D.stroke()
painter2D.restore()
}
function drawTime_second(painter2D,seconds)
{
let rotatoSecondAngle = (seconds * 6)*Math.PI/180 // 360°/60s=6°/s
painter2D.save()
painter2D.beginPath() // 必须加入
painter2D.translate(root.width/2,root.height/2) // 变换坐标起始点
painter2D.rotate(rotatoSecondAngle) // 旋转
painter2D.lineWidth=backgroundRadius*0.01;
painter2D.moveTo(0,backgroundRadius*0.15)
painter2D.lineTo(0,-backgroundRadius*0.8)
painter2D.stroke()
painter2D.restore()
}
function drawTime_minute(painter2D,minute)
{
let rotatoMinuteAngle = (minute * 6)*Math.PI/180 // 360°/60m=6°/m
painter2D.save()
painter2D.beginPath() // 必须加入
painter2D.translate(root.width/2,root.height/2) // 变换坐标起始点
painter2D.rotate(rotatoMinuteAngle) // 旋转
painter2D.lineWidth=backgroundRadius*0.02;
painter2D.moveTo(0,backgroundRadius*0.05)
painter2D.lineTo(0,-backgroundRadius*0.5)
painter2D.stroke()
painter2D.restore()
}
function drawTime_hour(painter2D,hour)
{
let rotatoHourAngle = (hour * 30)*Math.PI/180 // 360°/12h=30°/h
painter2D.save()
painter2D.beginPath() // 必须加入
painter2D.translate(root.width/2,root.height/2) // 变换坐标起始点
painter2D.rotate(rotatoHourAngle) // 旋转
painter2D.lineWidth=backgroundRadius*0.03;
painter2D.moveTo(0,backgroundRadius*0.05)
painter2D.lineTo(0,-backgroundRadius*0.3)
painter2D.stroke()
painter2D.restore()
}
}
关注
笔者 - jxd