?????????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 圖表” —— 剩下的只是配置系列、坐標軸和樣式。