前段时间有朋友找我做个问卷调查的软件,我说现在很多在线文档都有这功能,为啥还要使用Qt撸一个,他说要申请软著,我说,欧了。
我们先看看WPS在线问卷的统计中,柱状图统计的效果吧
我认为主要有以下几个关键点吧:
废话不多说,直接上代码了,ui文件就不放了,界面都是通过painter绘制的,没有任何控件。
- #ifndef BARGRAPHSTATISTIC_H
- #define BARGRAPHSTATISTIC_H
-
- #include
- #include
- #include
-
- namespace Ui {
- class BarGraphStatistic;
- }
-
- class BarGraphStatistic : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit BarGraphStatistic(const QVector
int >>& choices, QWidget *parent = nullptr); - ~BarGraphStatistic();
-
- protected:
- void paintEvent(QPaintEvent* e);
- void mouseMoveEvent(QMouseEvent* e);
- void resizeEvent(QResizeEvent* e);
-
- private:
- void UpdateBarRect();
-
- private:
- Ui::BarGraphStatistic *ui;
- QVector
int>> m_choices; - QString m_longestStr{""};
- int m_maxCnt{0};
-
-
- int m_fontSize{12};
- int m_padding{20};
- int m_itemHeight{45};
- int m_maxTxtWidth{200};
- int m_txtWidth;
- int m_txtHeight;
- int m_spaceHorizon{2};
-
- int m_axisXHeight{20};
-
- int m_winHeight;
- int m_barStartX;
-
- QVector
m_barRects; - int m_curBar = -1;
- QPoint m_mousePos;
- };
-
-
- #endif // BARGRAPHSTATISTIC_H
- #include "BarGraphStatistic.h"
- #include "ui_BarGraphStatistic.h"
- #include
- #include
- #include
- #include
-
- BarGraphStatistic::BarGraphStatistic(const QVector
int>>& choices, QWidget *parent) : - QWidget(parent),
- ui(new Ui::BarGraphStatistic),
- m_choices(choices)
- {
- ui->setupUi(this);
- setMouseTracking(true);
-
- for (int i = 0; i < m_choices.size(); ++i)
- {
- if (m_choices[i].first.size() > m_longestStr.size())
- m_longestStr = m_choices[i].first;
-
- if (m_choices[i].second > m_maxCnt)
- m_maxCnt = m_choices[i].second;
- }
-
- QFont f;
- f.setPixelSize(m_fontSize);
- QFontMetrics fm(f);
- auto tr = fm.boundingRect(m_longestStr);
- m_txtWidth = qMin(tr.width(), 100);
- m_txtHeight = tr.height();
-
- m_winHeight = m_padding * 2 + m_itemHeight * m_choices.size() + m_axisXHeight;
- m_barStartX = m_padding + m_txtWidth;
- setFixedHeight(m_winHeight);
-
-
- m_barRects.resize(m_choices.size());
- UpdateBarRect();
- }
-
- BarGraphStatistic::~BarGraphStatistic()
- {
- delete ui;
- }
-
- void BarGraphStatistic::paintEvent(QPaintEvent *e)
- {
- QPainter painter(this);
-
- {
- // draw background with white color
- painter.fillRect(this->rect(), QBrush(Qt::white));
- }
-
- {
- // draw axis
- painter.save();
- QPen pen;
- pen.setColor(Qt::gray);
- painter.setPen(pen);
-
- {
- int x0 = m_padding + m_txtWidth + m_spaceHorizon;
- int y0 = m_padding;
- int x1 = x0;
- int y1 = m_winHeight - m_padding - m_axisXHeight;
- painter.drawLine(x0, y0, x1, y1);
- }
- {
- int x0 = m_padding + m_txtWidth + m_spaceHorizon;
- int y0 = m_winHeight - m_padding - m_axisXHeight;
- int x1 = width() - m_padding;
- int y1 = y0;
- painter.drawLine(x0, y0, x1, y1);
- }
- {
- int x = m_padding + m_txtWidth + m_spaceHorizon;
- int y = m_padding + m_itemHeight * m_choices.size();
- int w = width() - x - m_padding;
- int h = m_axisXHeight;
- painter.drawText(x, y, w, h, Qt::AlignLeft, "0");
-
- painter.drawText(x, y, w, h, Qt::AlignRight, QString::number(m_maxCnt + 1));
- }
- painter.restore();
- }
-
-
- {
- painter.save();
- QFont f;
- f.setPixelSize(m_fontSize);
- painter.setFont(f);
-
- for (int i = 0; i < m_choices.size(); ++i)
- {
- {
- int x = m_padding;
- int y = m_padding + i * m_itemHeight;
- int w = m_txtWidth;
- int h = m_itemHeight;
-
- QFontMetrics fm(f);
- auto txt = fm.elidedText(m_choices[i].first, Qt::ElideRight, w);
-
- painter.drawText(QRect(x, y, w, h), Qt::AlignVCenter|Qt::AlignRight, txt);
- }
-
- {
- if (m_curBar == i)
- {
- painter.fillRect(m_barRects[i], QColor(10, 108, 255, 20));
- }
-
- int x = m_padding + m_txtWidth + m_spaceHorizon;
- int y = m_padding + i * m_itemHeight + m_itemHeight/4;
- int w = (width() - m_padding - m_txtWidth - m_spaceHorizon - m_padding) * m_choices[i].second / (m_maxCnt + 1);
- int h = m_itemHeight/2;
- painter.fillRect(x, y, w, h, QColor(10, 108, 255));
-
- x = x + w + m_spaceHorizon;
- y = m_padding + i * m_itemHeight;
- w = (width() - m_padding - m_txtWidth - m_spaceHorizon - m_padding) - w;
- h = m_itemHeight;
- painter.drawText(x, y, w, h, Qt::AlignVCenter|Qt::AlignLeft, QString::number(m_choices[i].second));
- }
- }
-
- if (m_curBar >=0 && m_curBar < m_choices.size())
- {
- painter.save();
- auto text = QString("%1: %2").arg(m_choices[m_curBar].first).arg(m_choices[m_curBar].second);
-
- auto font = painter.font();
- font.setPixelSize(12);
- QFontMetrics fm(font);
- auto br = fm.boundingRect(text);
-
- const int maxWidth = 500;
- auto w = qMin(maxWidth, br.width()+10);
- auto h = br.width() * br.height()/w +20;
-
- QRect rect;
- if (m_mousePos.x() + w + 10 > width())
- rect = QRect(m_mousePos + QPoint(-10-w, 10), QSize(w, h));
- else
- rect = QRect(m_mousePos + QPoint(10, 10), QSize(w, h));
-
- painter.setFont(font);
- QTextOption tOpt(Qt::AlignTop|Qt::AlignLeft);
- tOpt.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
- painter.drawText(rect, text, tOpt);
- painter.restore();
- }
- painter.restore();
- }
-
- }
-
- void BarGraphStatistic::mouseMoveEvent(QMouseEvent *e)
- {
- int cur = -1;
- for (int i = 0; i < m_barRects.size(); ++i)
- {
- if (m_barRects[i].contains(e->pos()))
- {
- cur = i;
- break;
- }
- }
-
- // if (cur != m_curBar)
- {
- m_curBar = cur;
- m_mousePos = e->pos();
- update();
- }
- }
-
- void BarGraphStatistic::resizeEvent(QResizeEvent *e)
- {
- UpdateBarRect();
- }
-
- void BarGraphStatistic::UpdateBarRect()
- {
- for (int i = 0; i < m_choices.size(); ++i)
- {
- int x = m_padding + m_txtWidth + m_spaceHorizon;
- int y = m_padding + i * m_itemHeight;
- int w = width() - m_padding - m_txtWidth - m_spaceHorizon - m_padding;
- int h = m_itemHeight;
-
- m_barRects[i] = QRect{x, y, w, h};
- }
- }
下面是我实现的最终效果,是不是还挺像的,如果感觉那里不好,大家就自己去修改源码吧。