Qt QBarSeries簡易柱狀圖教程


博客園最強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);

這樣就可以正常顯示值了。

到這里,本片教程就結束了,坑確實蠻多的,資料比較少,希望能幫到大家。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM