下面對QChartView進行封裝方便進行繪制:
#pragma once #include <QWidget> #include <QChart> #include <QChartView> #include <QBarSeries> #include <QBarSet> #include <QBarCategoryAxis> #include <QDebug> #include <QThread> #include <QValueAxis> #include <QMenu> #include "ui_QBarChart.h" QT_CHARTS_USE_NAMESPACE class ChartThreadDelegate : public QObject { Q_OBJECT public: explicit ChartThreadDelegate(QObject *parent = nullptr); ~ChartThreadDelegate(); void Working(QMap<QString, QVector<int>> & ValueVector, QBarSeries * BarSeries); private: signals: void ReturnSeries(QBarSet *); }; class QBarChart : public QChartView { Q_OBJECT public: QBarChart(QString ChartName,QWidget *parent = Q_NULLPTR); ~QBarChart(); void SetValue(QMap<QString, QVector<int>> & valuemap, QStringList & axisX); void ClearSeries(); void SetAxisYRange(int bottom,int top); private: Ui::QBarChart ui; //設置樣式 void SetStyle(); //chart對象 QChart Chart; //BarSet數量 int m_BarSetNum; //存儲柱狀圖對象 QBarSeries * BarSeries; //坐標 QBarCategoryAxis AxisX; QValueAxis AxisY; //線程類 QThread * m_Thread; ChartThreadDelegate * m_ChartThreadDelegate; private: QMap<QString, QVector<int>> ValueVector; QStringList AxisXValue; private slots: //動態添加柱狀圖 void Value(); void Series(QBarSet *); protected: void mousePressEvent(QMouseEvent *event); //鼠標懸停事件 virtual bool eventFilter(QObject * obj, QEvent * event); void contextMenuEvent(QContextMenuEvent *event); void createActions(); private: QMenu * PopMenu; QAction * ClearAction; private: signals: void selfClicked(); };
#include "QBarChart.h" #include <QGraphicsLayout> QBarChart::QBarChart(QString ChartName,QWidget *parent) : QChartView(parent) { ui.setupUi(this); //添加視圖 BarSeries = new QBarSeries(&Chart); BarSeries->setUseOpenGL(true); Chart.addSeries(BarSeries); //設置表格名稱 Chart.setTitle(ChartName); //坐標軸設置 Chart.createDefaultAxes(); Chart.setAcceptTouchEvents(true); //x坐標軸設置 Chart.setAxisX(&AxisX, BarSeries); //y坐標軸設置 AxisY.setRange(0, 100);//顯示數值范圍 Chart.setAxisY(&AxisY, BarSeries); //視圖添加柱狀圖 this->setChart(&Chart); //取消所有邊框 Chart.layout()->setContentsMargins(0, 0, 0, 0);//設置外邊界全部為0 Chart.setMargins(QMargins(0, 0, 0, 0));//設置內邊界全部為0 Chart.setBackgroundRoundness(0);//設置背景區域無圓角 //設置樣式 SetStyle(); //QValueAxis改變是會觸發信號 connect(&AxisX, &QBarCategoryAxis::categoriesChanged, this, &QBarChart::Value); m_Thread = new QThread; m_ChartThreadDelegate = new ChartThreadDelegate; m_ChartThreadDelegate->moveToThread(m_Thread); m_Thread->start(); connect(m_ChartThreadDelegate, &ChartThreadDelegate::ReturnSeries, this, &QBarChart::Series); this->setAttribute(Qt::WA_Hover, true); this->installEventFilter(this); createActions(); } QBarChart::~QBarChart() { } void QBarChart::SetValue(QMap<QString, QVector<int>> & valuemap, QStringList & axisX) { if (valuemap == ValueVector) {return; } ValueVector = valuemap; AxisXValue = axisX; AxisX.clear(); } void QBarChart::ClearSeries() { BarSeries->clear(); ValueVector.clear(); } void QBarChart::SetAxisYRange(int bottom, int top) { AxisY.setRange(bottom, top);//顯示數值范圍 } void QBarChart::SetStyle() { //Chart.setAnimationOptions(QChart::SeriesAnimations);//動畫效果 //BarSeries樣式設置 BarSeries->setLabelsPosition(QAbstractBarSeries::LabelsCenter);//在柱上顯示數值方式 //坐標軸樣式設置 AxisY.setGridLineVisible(false); //設置是否顯示網格線 //標簽樣式設置 Chart.legend()->setVisible(true); Chart.legend()->setAlignment(Qt::AlignBottom); //視圖樣式設置 //this->setRubberBand(QChartView::RectangleRubberBand);//拉伸效果 //this->setRenderHint(QPainter::Antialiasing); this->chart()->setTheme(QChart::ChartThemeLight); //窗口樣式設置 //QPalette pal = window()->palette(); //pal.setColor(QPalette::Window, QRgb(0x9e8965)); //pal.setColor(QPalette::WindowText, QRgb(0x404044)); //window()->setPalette(pal); } void QBarChart::Value() { BarSeries->clear(); QMapIterator<QString, QVector<int>> ValueMapIteator(ValueVector); //m_ChartThreadDelegate->Working(ValueVector, BarSeries); while (ValueMapIteator.hasNext()) { ValueMapIteator.next(); QBarSet * barset = new QBarSet(ValueMapIteator.key()); QVector<int> ValueVector = ValueMapIteator.value(); QVector<int>::iterator ValueVectorIterator; for (int ValueVectorIterator : ValueVector) { barset->append(ValueVectorIterator); } BarSeries->append(barset); } AxisX.append(AxisXValue); } void QBarChart::Series(QBarSet * Set) { BarSeries->append(Set); } void QBarChart::mousePressEvent(QMouseEvent * event) { emit selfClicked(); } bool QBarChart::eventFilter(QObject * obj, QEvent * event) { if (event->type() == QEvent::HoverEnter) { BarSeries->setLabelsVisible(true);//判斷是否在圖柱上顯示數值 return true; } if (event->type() == QEvent::Leave) { BarSeries->setLabelsVisible(false);//判斷是否在圖柱上顯示數值 return true; } return QWidget::eventFilter(obj, event); } ChartThreadDelegate::ChartThreadDelegate(QObject *parent) : QObject(parent) { } ChartThreadDelegate::~ChartThreadDelegate() { } void ChartThreadDelegate::Working(QMap<QString, QVector<int>>& ValueVector, QBarSeries * BarSeries) { BarSeries->clear(); QMapIterator<QString, QVector<int>> ValueMapIteator(ValueVector); while (ValueMapIteator.hasNext()) { ValueMapIteator.next(); QBarSet * barset = new QBarSet(ValueMapIteator.key()); QVector<int> ValueVector = ValueMapIteator.value(); QVector<int>::iterator ValueVectorIterator; for (int ValueVectorIterator : ValueVector) { barset->append(ValueVectorIterator); } BarSeries->append(barset); //emit ReturnSeries(barset); } } void QBarChart::createActions() { //創建菜單、菜單項 PopMenu = new QMenu(); ClearAction = new QAction(this); ClearAction->setText(QStringLiteral("清空表格")); //連接信號與槽 connect(ClearAction, &QAction::triggered, this, &QBarChart::ClearSeries); } void QBarChart::contextMenuEvent(QContextMenuEvent *event) { //清除原有菜單 PopMenu->clear(); PopMenu->addAction(ClearAction); //菜單出現的位置為當前鼠標的位置 PopMenu->exec(QCursor::pos()); event->accept(); }
繪制時只需要在ui文件中添加一個QGridLayout對象,然后調用ui.GridLayout->addWidget(mChart);即可完成柱狀圖添加
更改數據時可通過QBarChart類中的SetValue方法設置柱狀圖內容,SetAxisYRange方法修改Y軸刻度即可