在 QML 中,我们经常会遇到二维绘图和绘点的需求。Qt 官方目前主推的现代绘图方案是 Qt Graphs,它支持二维和三维绘图,并引入了 GPU 加速,是官方最推荐的绘图方式。
但是在使用过程中,会发现 二维平面绘图的支持并不理想,例如实现平移和缩放时效果比较麻烦,也不够直观。因此,笔者决定继续使用之前的绘图方案——Qt Charts。Qt Charts 在缩放和平移方面提供了比较成熟和方便的实现方法。
在实际使用 Qt Charts 时,会遇到一个问题:QML 可以直接引用 Qt Graphs 的库而没有问题,但如果引入 Qt Charts 库,程序会直接闪退。
经过排查,最终解决方案如下:
-
将头文件
#include <QGuiApplication>改为:
#include <QApplication>
-
将程序入口中的对象修改为:
QApplication app(argc, argv);
这样即可解决程序闪退的问题,同时能够顺利使用 Qt Charts 的缩放和平移功能。
附上测试代码
// ChartView: 显示曲线的控件
ChartView {
id: chart
anchors.fill: parent
antialiasing: true
backgroundColor: Qt.rgba(1, 1, 1, 0.5) // 整体背景透明
// 定义坐标轴
ValueAxis { id: axisX; min: -5; max: 5 }
ValueAxis { id: axisY; min: -5; max: 5 }
// 自定义 X 轴标题
Text {
text: "X 轴" // 显示的文字内容,这里是 X 轴的标题
color: "white" // 文字颜色,这里设置为白色
font.pixelSize: 16 // 文字大小,以像素为单位
anchors.horizontalCenter: chart.horizontalCenter // 水平方向居中对齐 ChartView
anchors.bottom: chart.bottom // 垂直方向底部对齐 ChartView 的底部
anchors.bottomMargin: 8 // 离 ChartView 底部的距离为 8 像素
}
// 自定义 Y 轴标题
Text {
text: "Y 轴"
color: "white"
font.pixelSize: 16
rotation: -90
anchors.verticalCenter: chart.verticalCenter
anchors.left: chart.left
anchors.leftMargin: 8
}
// 样条曲线 (LineSeries + pointsVisible)
SplineSeries {
name: "Spline"
axisX: axisX
axisY: axisY
useOpenGL: true // 提升渲染性能
pointsVisible: true // 显示每个数据点
pointLabelsVisible: true // 显示数值标签
color: "blue"
// 曲线数据点
XYPoint { x: 0; y: 0 }
XYPoint { x: 1; y: 2 }
XYPoint { x: 2; y: 1 }
XYPoint { x: 3; y: 3 }
XYPoint { x: 4; y: 2 }
}
// ----------------------------
// 鼠标拖拽平移和缩放功能
// ----------------------------
MouseArea {
anchors.fill: parent
property real lastX: 0
property real lastY: 0
hoverEnabled: true
acceptedButtons: Qt.AllButtons
// 鼠标按下记录初始位置
onPressed: function(event) {
lastX = event.x
lastY = event.y
}
// 鼠标移动平移
onPositionChanged: function(event) {
if (!event.buttons) return // ✅ 只有鼠标按下才平移
var dx = event.x - lastX
var dy = event.y - lastY
// 横轴平移
var xRange = axisX.max - axisX.min
axisX.min -= dx / chart.width * xRange
axisX.max -= dx / chart.width * xRange
// 纵轴平移
var yRange = axisY.max - axisY.min
axisY.min += dy / chart.height * yRange
axisY.max += dy / chart.height * yRange
lastX = event.x
lastY = event.y
}
// 鼠标滚轮缩放
onWheel: function(event) {
if (!axisX || !axisY) return
var factor = event.angleDelta.y > 0 ? 0.9 : 1.1
var xCenter = (axisX.min + axisX.max) / 2
var yCenter = (axisY.min + axisY.max) / 2
var xRange = (axisX.max - axisX.min) * factor
var yRange = (axisY.max - axisY.min) * factor
// 限制最小/最大范围
var minRange = 0.01
var maxRangeX = 100
var maxRangeY = 100
xRange = Math.max(minRange, Math.min(xRange, maxRangeX))
yRange = Math.max(minRange, Math.min(yRange, maxRangeY))
axisX.min = xCenter - xRange / 2
axisX.max = xCenter + xRange / 2
axisY.min = yCenter - yRange / 2
axisY.max = yCenter + yRange / 2
}
}
}
5153

被折叠的 条评论
为什么被折叠?



