博客園最強Qt QBarSeries簡易柱狀圖教程
前情提要
每個人的繪圖需求不同,此篇教程也是根據需求來改的。我的需求大概如下所示。
- 通過信號槽的方式接收signals來刷新柱狀圖,所以每次觸發信號,就要刷新一次柱狀圖。
- 柱狀圖的橫縱坐標,都是動態設置可變的。(通過信號傳入的參數來改變)
- 需要顯示柱狀圖的值信息,即每根柱子的值
- 最基礎的當然就是沒有bug,不崩潰
准備工作
- 在pro文件中添加charts模塊
QT += charts
- 引用
#include <QtCharts>
方便起見,直接引用,不需要單獨引用某一個模塊。
涉及對象介紹
-
QChartView
用於存放QChart的控件,顯示表格,在基礎控件中不存在,需要手動將控件添加到“窗體”中。
-
QChart
用於存放表格的對象,可以同時存放多個表格對象。
-
QBarSeries(某一種表格對象)
用於存放此表格中所有的“柱子”對象。
-
QBarSet("柱子")
用於顯示一系列柱子。單個QBarSet的柱子數量應該根據對應顯示的橫縱坐標來設置。
-
QBarCategoryAxis
將“柱子”分類的表格坐標。(橫縱坐標均可,此教程中為橫坐標)
比如QBarCategoryAxis中的category個數為10,那么每個QBarSet都應該有10個值。
-
QValueAxis
用於顯示”柱子“值的坐標。(橫縱坐標均可,此教程中為縱坐標)
開始實戰
初始版本
初始版本,直接初始化就顯示一個完整的柱狀圖
barSeries = new QBarSeries();
barCategoryAxisX = new QBarCategoryAxis();
valueAxisY = new QValueAxis();
chart = new QChart();
chartView = new QChartView(this);
barOK = new QBarSet("OK");
barNG = new QBarSet("NG");
barNAN = new QBarSet("NAN");
barOK->append(10);
barNG->append(2);
barNAN->append(3);
barSeries->append(barOK);
barSeries->append(barNG);
barSeries->append(barNAN);
barCategoryAxisX->append("Row1");
valueAxisY->setRange(0,10);
valueAxisY->setTickCount(3);//設置value網格數
chart->addSeries(barSeries);
chart->setAxisX(barCategoryAxisX, barSeries);
chart->setAxisY(valueAxisY, barSeries);
chart->setTitle(u8("檢查結果柱狀圖"));
chart->setAnimationOptions(QChart::SeriesAnimations);
chartView->setRenderHint(QPainter::Antialiasing);
chartView->setChart(chart);
ui->verticalLayout->addWidget(chartView);
這個,我相信大家都會,Qt的官方教程都有,但是如果需要通過信號槽來刷新呢?
刷新版本
既然是刷新版本,所以需要更新X、Y坐標軸,更新“柱子”的內容。
- 因為都是通過指針的方式添加,所以最好的方式當然就是每個都clear重新分配內存。QBarSet除了手動析構外沒有,比較好的辦法,通過查詢可知,可以通過QBarSeries來釋放。
barSeries.clear();
barOK = new QBarSet("OK");
barNG = new QBarSet("NG");
barNAN = new QBarSet("NAN");
barSeries->append(barOK);
barSeries->append(barNG);
barSeries->append(barNAN);
- 至於橫縱坐標,通過clear后重新設置即可。
barCategoryAxisX->clear();
barCategoryAxisX->append("Row1");
valueAxisY->setRange(0, 10);//動態值
valueAxisY->setTickCount(3);
chart->setAxisX(barCategoryAxisX, barSeries);
chart->setAxisY(valueAxisY, barSeries);
至此,應該再次觸發刷新,就可以了,但是很遺憾,添加上述函數,再次刷新,會導致程序崩潰。
為什么呢?
其實很簡單,因為
chart->setAxisX();
這個函數會手動delete掉,設置后面的barSeries之前的那個series。因為都是同一個series,所以只要重新設置X、Y軸,就會刪掉barSeries。
但是無論你barSeries怎么修改,哪怕是重新new一個對象,好像都會崩潰。
這個時候,查閱qt官方文檔,你會發現,原來官方在設置X、Y之前還有一個createDefaultAxes()這個函數。隨即在setAxisX()之前加上這句。
chart->createDefaultAxes();
然后,就會發現,崩潰是沒有了,但是好像刷新之后啥都沒有。
仔細想想,可能是需要重新設置barSeries,於是分別添加了如下代碼
chart->removeAllSeries();
chart->addSeries(barSeries);
讓chart也刷新一次。
chartView->setChart(chart);
可惜可惜,又崩潰了,其實很簡單,removeAllSeries之后,barSeries對象被delete掉,需要重新分配內存,即
chart->removeAllSeries();
barSeries = new QBarSeries();
chart->addSeries(barSeries);
這樣的話,刷新的時候,“柱子”有了。大致代碼如下
void flush()
{
barCategoryAxisX->clear();
chart->removeAllSeries();
barSeries->clear();
barSeries = new QBarSeries();
barOK = new QBarSet("OK");
barNG = new QBarSet("NG");
barNAN = new QBarSet("NAN");
barSeries->append(barOK);
barSeries->append(barNG);
barSeries->append(barNAN);
chart->createDefaultAxes();
valueAxisY->setRange(0, 10);
valueAxisY->setTickCount(3);
//......append數據到barset
chart->addSeries(barSeries);
chart->setAxisX(barCategoryAxisX, barSeries);
chart->setAxisY(valueAxisY, barSeries);
chartView->setChart(chart);
}
顯示值版本
因為需求,我們需要將值顯示到“柱子”上。查找資料可得到如下代碼:
barSeries->setLabelsPosition(QAbstractBarSeries::LabelsOutsideEnd);
barSeries->setLabelsVisible(true);
這樣的確可以,顯示值到“柱子”的上方,但是很遺憾,運行的時候,啥都沒有,因為默認的barSet的labelColor為white,也就是跟背景色一致了。那么我們可以采取換背景色的方案,也可以采取換label顏色的方案。這里采取換label顏色的方案。
label的顯示設置取決於barSeries,但是,找遍了chart和barSeries都沒有找到關於label字體、顏色等參數的設置,最后在barset中找到了setLabel相關的參數。
barOK->setLabelColor(Qt::black);
barNG->setLabelColor(Qt::black);
barNAN->setLabelColor(Qt::black);
這樣就可以正常顯示值了。
到這里,本片教程就結束了,坑確實蠻多的,資料比較少,希望能幫到大家。