工程配置
CMake文件
find_package(Qt5 COMPONENTS Charts REQUIRED)target_link_libraries(zhd-desktop PRIVATE Qt5::Charts)
包含頭文件以及名稱空間(這個很重要,沒有包含名稱空間編譯器會提示找不到相關的類型)
#include <QtCharts>using namespace QtCharts;
初始化
初始化Chart
// 創建圖表
QChart *chart = new QChart();
chart->setTitle("Valve Data");// 隱藏圖例
chart->legend()->setVisible(false);// 創建圖表視圖
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);QHBoxLayout *hLayout = new QHBoxLayout(ui->view);
hLayout->addWidget(chartView);
hLayout->setContentsMargins(0, 0, 0, 0);
波形
每一道波形就是一個QLineSeries
,每個QLineSeries
都要和X軸和Y軸進行綁定
m_temperature = new QLineSeries();
m_temperature->setColor(Qt::red);
m_temperature->setPointsVisible(true);m_pressure = new QLineSeries();
m_pressure->setColor(Qt::blue);
m_pressure->setPointsVisible(true);m_position = new QLineSeries();
m_position->setColor(Qt::black);
m_position->setPointsVisible(true);m_pressureSetpt = new QLineSeries();
m_pressureSetpt->setColor(Qt::darkYellow);
m_pressureSetpt->setPointsVisible(true);
為了使波形更有區分度,需要配置不同的顏色,建議跟Y軸刻度的顏色保持一致,特別是軸比較多的情況下
void setAxisColor(QAbstractAxis *axis, const QColor &color)
{axis->setGridLineColor(color);axis->setLinePenColor(color);axis->setLabelsColor(color);axis->setTitleBrush(color);
}
X軸
X軸一般是時間軸,時分秒格式:hh:mm:ss
QDateTimeAxis *timeAxis = new QDateTimeAxis();
timeAxis->setTitleText("Time");
timeAxis->setFormat("hh:mm:ss");
chart->addAxis(timeAxis, Qt::AlignBottom);
series1->attachAxis(timeAxis);
series2->attachAxis(timeAxis);
Y軸
Y軸:左側和右側都可以添加刻度尺
// 左側刻度尺
QValueAxis *pressureSetpt = new QValueAxis();
pressureSetpt->setTitleText("Pressure Setpt (Torr)");
pressureSetpt->setRange(0, 25);
chart->addAxis(pressureSetpt, Qt::AlignLeft);
series1->attachAxis(pressureSetpt);QValueAxis *pressure = new QValueAxis();
pressure->setTitleText("Pressure (Torr)");
pressure->setRange(0, 25);
chart->addAxis(pressure, Qt::AlignLeft);
series1->attachAxis(pressure);// 右側刻度尺
QValueAxis *driverTemperature = new QValueAxis();
driverTemperature->setTitleText("Driver temperature");
driverTemperature->setRange(0, 100);
chart->addAxis(driverTemperature, Qt::AlignRight);
series2->attachAxis(driverTemperature);QValueAxis *positionAxis = new QValueAxis();
positionAxis->setTitleText("Position (%)");
positionAxis->setRange(0, 100);
chart->addAxis(positionAxis, Qt::AlignRight);
series2->attachAxis(positionAxis);
繪圖
實時繪制波形點:往QLineSeries里邊添加數據,用append接口
QDateTime currentTime = QDateTime::currentDateTime();
if(m_resumePause) {m_timeAxis->setRange(currentTime.addSecs(-10), currentTime);
}if(m_channels[0]) {m_pressure->append(currentTime.toMSecsSinceEpoch(), pressure);if (m_pressure->count() > m_max) {m_pressure->remove(0);}
}if(m_channels[1]) {m_position->append(currentTime.toMSecsSinceEpoch(), position);if (m_position->count() > m_max) {m_position->remove(0);}
}if(m_channels[2]) {m_pressureSetpt->append(currentTime.toMSecsSinceEpoch(), pressureSetpt);if (m_pressureSetpt->count() > m_max) {m_pressureSetpt->remove(0);}
}if(m_channels[3]) {m_temperature->append(currentTime.toMSecsSinceEpoch(), valveTemperature);if (m_temperature->count() > m_max) {m_temperature->remove(0);}
}
注意事項:
1.時間軸要實時移動到正確的時間窗口范圍
2.QLineSeries
波形點之后到達一定的數據量需要刪除一些點以確保buffer不會寫爆(頻繁申請內存導致卡頓)
進階
QtCharts自帶的時間軸比較丑陋,如果想要定制的話,可以參考以下方法進行樣式修改
- 自定義
QValueAxis
作為X軸 - 捕獲
QValueAxis::rangeChanged
信號,獲取QChartView
里邊的scene
,同時也可以獲取到刻度的左右邊界min
和max
- 刪除
scene
(QGraphicsScene)里邊的所有items
,即原有的刻度不要了 - 在
QGraphicsScene
即基礎上畫刻度,每一個刻度就是一個QGraphicsLineItem
代碼參考
// 動態修改 X 軸標簽為時間格式,并繪制刻度線
QObject::connect(axisX, &QValueAxis::rangeChanged, [axisX, chartView](qreal min, qreal max) {QGraphicsScene *scene = chartView->scene();// 檢查 min 和 max 是否有效if (qIsNaN(min) || qIsNaN(max) || qIsInf(min) || qIsInf(max)) {// qWarning() << "Invalid min or max value:" << min << max;return;}// 檢查 plotArea 是否有效if (chartView->chart()->plotArea().width() <= 0 || chartView->chart()->plotArea().height() <= 0) {// qWarning() << "Invalid plot area size";return;}// 清除舊的標簽和刻度線for (QGraphicsItem *item : scene->items()) {if (item->data(0).toString() == "custom_label" || item->data(0).toString() == "custom_line") {scene->removeItem(item);delete item;}}// 生成 10 個刻度int tickCount = 10; // 總共 10 個刻度qreal tickInterval = (max - min) / (tickCount - 1); // 計算刻度間隔for (int i = 0; i < tickCount; ++i) {qreal value = min + i * tickInterval;// 檢查 value 是否有效if (qIsNaN(value) || qIsInf(value)) {// qWarning() << "Invalid value:" << value;continue;}QDateTime dateTime = QDateTime::fromSecsSinceEpoch(value);// 計算刻度線的位置qreal x = chartView->chart()->plotArea().left() +(value - min) / (max - min) * chartView->chart()->plotArea().width();// 檢查 x 是否有效if (qIsNaN(x) || qIsInf(x)) {// qWarning() << "Invalid x coordinate:" << x;continue;}// 只在偶數刻度繪制時間標簽和黑線if (i % 2 == 0) {// 繪制時間標簽QString label = dateTime.toString("hh:mm:ss");QGraphicsTextItem *textItem = scene->addText(label);qreal textWidth = textItem->boundingRect().width(); // 獲取標簽寬度qreal textHeight = textItem->boundingRect().height(); // 獲取標簽高度// 調整標簽位置,使其居中對齊刻度線textItem->setPos(x - textWidth / 2, chartView->chart()->plotArea().bottom() + 10);textItem->setData(0, "custom_label"); // 標記為自定義標簽// 繪制黑線qreal lineLength = 10; // 刻度線長度QGraphicsLineItem *lineItem = scene->addLine(x, chartView->chart()->plotArea().bottom(),x, chartView->chart()->plotArea().bottom() + lineLength,QPen(Qt::black));lineItem->setData(0, "custom_line"); // 標記為自定義刻度線}}
});
打包
軟件打包,需要添加Qt5Charts這個dll
Qt5Charts.dll
版權
版權問題,商用的話可能會被Qt請喝茶