QML输入控件:Dial外观深度定制(4)
目录
简介
相关阅读
实现效果展示
实现步骤
1. 定义属性
2. Dial控件基本配置
3. 使用Canvas绘制刻度
3.1 主刻度绘制
3.2 刻度标签
3.3 子刻度绘制
3.4 当前值指示器
4. 中心值显示
运行效果
总结
完整工程下载
简介
Dial(表盘)控件是QML中一个常用的输入组件,类似于旋钮或圆形滑块。本文将介绍如何通过自定义绘制来创建一个带有刻度、标签和中心值显示的精美Dial控件。
相关阅读
Dial QML Type | Qt Quick Controls 6.8.3
Canvas QML Type | Qt Quick 6.8.3
QML输入控件:Dial联动、音频均衡器的实现 (3)-CSDN博客
实现效果展示
实现步骤
接下来要实现一个QML示例,创建一个带有自定义刻度的旋钮(Dial)控件。它展示了如何使用 QML 的 Canvas 组件来绘制自定义的图形和文本,并结合 Dial 控件来实现一个动态的仪表盘效果。以下是详细的实现步骤:
1. 定义属性
首先,我们定义了一些全局属性来控制Dial的外观:
property color tickColor: "#606060" // 刻度颜色
property color activeTickColor: "#e74c3c" // 当前值指示器颜色
property int tickCount: 12 // 主刻度数量
property int subTickCount: 4 // 每个主刻度之间的子刻度数量
property double startAngle: -140 // 起始角度
property double endAngle: 140 // 结束角度
- tickColor:主刻度的颜色,默认为深灰色。
- activeTickColor:当前值指示器的颜色,默认为红色。
- tickCount:主刻度的数量,默认为 12。
- subTickCount:每个主刻度之间的子刻度数量,默认为 4。
- startAngle 和 endAngle:定义了旋钮的起始角度和结束角度,单位为度。这里设置为从 -140 度到 140 度,总共覆盖 280 度。
2. Dial控件基本配置
Dial {
id: dial
anchors.centerIn: parent
width: Math.min(parent.width, parent.height) * 0.8
height: width
from: 0
to: 100
value: 50
stepSize: 1
handle: null // 隐藏默认手柄
}
这里设置了Dial的基本属性,包括尺寸、值范围和步进值。通过将handle设为null来隐藏默认的手柄显示。
- from: 0 和 to: 100:定义了 Dial 控件的值范围,从 0 到 100。
- value: 50:初始值为 50。
- stepSize: 1:每次旋转的步长为 1。
3. 使用Canvas绘制刻度
在background属性中使用Canvas来自定义绘制刻度:
background: Canvas {
id: dialCanvas
anchors.fill: parent
rotation: -90
onPaint: {
var ctx = getContext("2d")
ctx.reset()
const centerX = width / 2
const centerY = height / 2
const outerRadius = width / 2 - 10
const innerRadius = outerRadius - 15
const subInnerRadius = outerRadius - 8
- Canvas:用于绘制自定义图形。
- rotation: -90:将 Canvas 旋转 -90 度,使角度计算更直观(从顶部开始绘制)。
- onPaint:Canvas 的绘制事件,当需要重新绘制时触发。
- getContext("2d"):获取 2D 绘图上下文。
- ctx.reset():清除之前的绘制内容。
- 定义了绘制时使用的中心点、外半径、内半径和子刻度内半径。
3.1 主刻度绘制
// 绘制主刻度
ctx.strokeStyle = tickColor
ctx.lineWidth = 1.5
for (var i = 0; i <= tickCount; i++) {
var angle = (startAngle + (endAngle - startAngle) * (i / tickCount)) * Math.PI / 180
ctx.beginPath()
ctx.moveTo(
centerX + innerRadius * Math.cos(angle),
centerY + innerRadius * Math.sin(angle)
)
ctx.lineTo(
centerX + outerRadius * Math.cos(angle),
centerY + outerRadius * Math.sin(angle)
)
ctx.stroke()
// 绘制刻度标签 ...
}
使用循环绘制主刻度线,并在每个刻度位置计算角度。
3.2 刻度标签
// 绘制刻度标签
ctx.fillStyle = tickColor
ctx.font = '12px sans-serif'
ctx.textAlign = "center"
ctx.textBaseline = "middle"
var labelRadius = outerRadius - 25
var labelValue = dial.from + (dial.to - dial.from) * (i / tickCount)
ctx.save()
ctx.translate(
centerX + labelRadius * Math.cos(angle),
centerY + labelRadius * Math.sin(angle)
)
ctx.rotate(angle + Math.PI/2)
ctx.fillText(labelValue.toFixed(0), 0, 0)
ctx.restore()
为每个主刻度添加对应的数值标签。使用save()和restore()来保证文本旋转不影响其他绘制操作。
3.3 子刻度绘制
// 绘制子刻度
if (subTickCount > 0) {
ctx.lineWidth = 1
for (i = 0; i <= tickCount * subTickCount; i++) {
angle = (startAngle + (endAngle - startAngle) * (i / (tickCount * subTickCount))) * Math.PI / 180
if (i % subTickCount === 0) continue
ctx.beginPath()
ctx.moveTo(
centerX + subInnerRadius * Math.cos(angle),
centerY + subInnerRadius * Math.sin(angle)
)
ctx.lineTo(
centerX + outerRadius * Math.cos(angle),
centerY + outerRadius * Math.sin(angle)
)
ctx.stroke()
}
}
在主刻度之间添加更细、更短的子刻度,提升精确度。
3.4 当前值指示器
// 高亮当前值刻度(改为更细的指示线)
var activeAngle = dial.angle * Math.PI / 180
ctx.strokeStyle = activeTickColor
ctx.lineWidth = 2
ctx.beginPath()
ctx.moveTo(
centerX + (innerRadius-10) * Math.cos(activeAngle),
centerY + (innerRadius-10) * Math.sin(activeAngle)
)
ctx.lineTo(
centerX + outerRadius * Math.cos(activeAngle),
centerY + outerRadius * Math.sin(activeAngle)
)
ctx.stroke()
使用不同颜色和粗细的线条来显示当前值的位置。
4. 中心值显示
// 中心值显示(带背景提升可读性)
Rectangle {
anchors.centerIn: parent
width: valueLabel.width + 20
height: valueLabel.height + 10
radius: 5
color: "#f0f0f0"
border.color: "#c0c0c0"
Label {
id: valueLabel
anchors.centerIn: parent
text: dial.value.toFixed(1)
font.pixelSize: 24
color: activeTickColor
}
}
在Dial中心添加一个带背景的数值显示,实时显示当前值。
运行效果
控件呈现为圆形旋钮形态:
- 12个主刻度带数字标签(0-100),每个主刻度间包含4个子刻度
- 红色指示线实时反映当前数值,支持鼠标拖拽和精准数值调整
- 中心区域显示精确到小数点后一位的当前值
总结
本文实现了一个功能完善的刻度旋钮控件,实现要点包括:
- 合理运用Canvas进行复杂图形绘制
- 数学计算实现精确的刻度定位
- 属性绑定实现数据驱动视图
完整工程下载
https://gitcode.com/u011186532/qml_demo/tree/main/qml_dial