ChartView的基本使用
Qt ChartView(准确类名 QChartView)是 Qt Charts 模块里最常用的图表显示控件。一句话概括:“它把 QChart 画出来,并自带缩放、平移、抗锯齿等交互能力”。
QML ChartView 简介(一句话先记住:ChartView 是 QML 场景里用来“装”各种图表的容器)
一、ChartView的基本知识
类型:
ChartView
(QtQuick 2.x 场景里的标准 Item)模块:
import QtCharts 2.15
(或 2.3/2.5/2.12 视 Qt 版本而定)作用:把 Qt Charts 的所有图表(折线、柱状、饼图、面积、散点、极坐标……)直接渲染到 QML 界面,并自带动画、缩放、交互、主题等功能
最小可运行代码,运行即可看到带标题、动画过渡的折线图
QT += core gui widgets charts qml quick
#include <QApplication>
#include <QGuiApplication>
#include <QQmlApplicationEngine>int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endifQApplication 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();
}
import QtQuick 2.15
import QtQuick.Window 2.15
import QtCharts 2.15Window {visible: truewidth: 640; height: 480title: qsTr("ChartView 最小示例")ChartView {anchors.fill: parenttitle: "温度"LineSeries {name: "T"XYPoint { x: 0; y: 20 }XYPoint { x: 1; y: 25 }XYPoint { x: 2; y: 23 }}}
}
关键属性速查
功能 | 常用属性 | 示例值 |
---|---|---|
图表标题 | title / titleColor / titleFont | "销售额" |
外观主题 | theme | ChartView.ChartThemeDark |
动画 | animationOptions | ChartView.SeriesAnimations |
背景 | backgroundColor / backgroundRoundness | "#1e1e1e" |
图例 | legend.visible / legend.alignment | false / Qt.AlignBottom |
边距 | margins.top / margins.left … | 10 |
缩放 | zoomIn() / zoomOut() / resetZoom() | 方法调用 |
鼠标交互 | 内部自带 MouseArea 或自定义 |
数据绑定与动态更新
方案 A:在 纯 QML 里用 Timer
定时追加数据
import QtQuick 2.15
import QtQuick.Window 2.15
import QtCharts 2.15Window {visible: truewidth: 640; height: 480title: qsTr("ChartView 实时刷新")ChartView {id: chartanchors.fill: parenttitle: "温度"animationOptions: ChartView.SeriesAnimations // 开启动画// X、Y 轴ValueAxis {id: axisXmin: 0max: 10 // 初始横轴 10 个点titleText: "采样次数"}ValueAxis {id: axisYmin: 15max: 35titleText: "温度 (°C)"}LineSeries {id: seriesname: "T"axisX: axisXaxisY: axisY}}/* ---------- 定时刷新 ---------- */Timer {interval: 800 // 800 ms 一次running: truerepeat: trueonTriggered: {const x = series.count // 当前点数const y = 20 + Math.random()*10 // 模拟 20~30 °Cseries.append(x, y)// 简单的滚动窗口:超过 10 个点就整体右移if (x > 10) {axisX.min += 1axisX.max += 1}}}
}
方案 B:在 C++ 里用信号触发刷新
(适合真正的大数据/硬件采集,UI 不卡顿)
#ifndef DATASOURCE_H
#define DATASOURCE_H#include <QObject>
#include <QTimer>
#include <QRandomGenerator>// dataSource.h
class DataSource : public QObject {Q_OBJECT
public:explicit DataSource(QObject *parent = nullptr) : QObject(parent) {m_timer.setInterval(500);connect(&m_timer, &QTimer::timeout, this, &DataSource::generate);m_timer.start();}signals:void newPoint(qreal x, qreal y);private:void generate() {static int i = 0;emit newPoint(i++, 20 + QRandomGenerator::global()->generateDouble()*10);}QTimer m_timer;
};#endif // DATASOURCE_H
#include <QApplication>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>#include <DataSource.h>int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endifQApplication app(argc, argv);QQmlApplicationEngine engine;DataSource src;engine.rootContext()->setContextProperty("dataSrc", &src);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();
}
import QtQuick 2.15
import QtQuick.Window 2.15
import QtCharts 2.15Window {visible: truewidth: 640; height: 480title: qsTr("ChartView 实时刷新")ChartView {id: chartanchors.fill: parenttitle: "温度"animationOptions: ChartView.SeriesAnimations // 开启动画// X、Y 轴ValueAxis {id: axisXmin: 0max: 10 // 初始横轴 10 个点titleText: "采样次数"}ValueAxis {id: axisYmin: 15max: 35titleText: "温度 (°C)"}LineSeries {id: seriesname: "T"axisX: axisXaxisY: axisY}}Connections {target: dataSrcfunction onNewPoint(x, y) {series.append(x, y);if (x > 10) {axisX.min += 1;axisX.max += 1;}}}
}
常用系列类型
LineSeries
折线SplineSeries
平滑曲线AreaSeries
面积ScatterSeries
散点BarSeries
/StackedBarSeries
柱状PieSeries
饼图PolarChartView
极坐标图(继承自 ChartView 的特化)
坐标轴
ChartView 不会自动创建轴,需要手动声明并绑定:
ValueAxis {id: axisXmin: 0; max: 10tickCount: 6
}
ValueAxis {id: axisYmin: 0; max: 100
}
LineSeries {axisX: axisXaxisY: axisY
}
大数据刷新
在大数据量(场景下,ChartView 的动画、抗锯齿、OpenGL 加速等设置都会影响性能。
真·实时刷新 超过几万点后,
append()
会开始卡顿。
建议:
• 使用replace()
替换整条数组,而不是逐点append()
• 或者自己实现降采样(只保留最新 N 点)。Qt 版本差异
•useOpenGL
在 Qt 6 已经废弃,Qt 6 默认就是 GPU 管线,无需设置。
• 若用 Qt 6,只需animationOptions: ChartView.NoAnimation
即可。
import QtQuick 2.15
import QtQuick.Window 2.15
import QtCharts 2.15Window {visible: truewidth: 800; height: 500title: qsTr("大数据折线图,需等待")ChartView {id: chartanchors.fill: parenttitle: "温度曲线"animationOptions: ChartView.NoAnimation // 关动画antialiasing: false // 关抗锯齿ValueAxis { id: axisX; min: 0; max: 10000 }ValueAxis { id: axisY; min: 15; max: 35 }LineSeries {id: seriesaxisX: axisXaxisY: axisYuseOpenGL: true // 用 GPU}}Component.onCompleted: {for (let i = 0; i < 10000; ++i)series.append(i, 20 + Math.sin(i * 0.01) * 5);}
}
设置 | 作用 | 备注 |
---|---|---|
animationOptions: ChartView.NoAnimation | 彻底关闭系列动画,减少 CPU/GPU 负载 | 大数据必备 |
antialiasing: false | 关闭边缘平滑,每帧少一次全屏混合 | 视觉略差,性能提升明显 |
renderTarget: ChartView.GL | 让 ChartView 整体用 OpenGL 渲染 | Qt 5.11+ 支持 |
LineSeries.useOpenGL: true | 把折线交给 GPU 画 | 必须 与上一条一起用 |
QML ChartView = “在 QML 里拖一个矩形就能画出任何 Qt Charts 图表” —— 剩下的只是配置系列、坐标轴和样式。