昨天在玩手机游戏时,见到一个游戏的饼状投票统计图很漂亮,所以我今天也花了一个下午来实现了一个类似的程序娱乐一下,呵呵。
思路:
1:将窗体设为Qt::FramelessWindowHint和Qt::WA_TranslucentBackground(去掉标题栏,背景透明)。
2:重载程序的鼠标事件(移动程序)和键盘事件(模拟投票和退出)。
3:根据投票结果,在paintEvent函数中画几个扇形和其他东西。
操作说明:
1:按数字键0-9模拟投票。
2:按ESC键退出程序。
运行时截图(浅绿色的是桌面背景):
源代码:
main.cpp
1 2 3 4 5 6 7 8 9 10 11 |
#include "piedialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); PieDialog w; w.show(); return a.exec(); } |
piedialog.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#ifndef PIEDIALOG_H #define PIEDIALOG_H #include <QDialog> class PieDialog : public QDialog { Q_OBJECT private: int m_Result[10]; QColor m_Color[10]; QPoint m_CurrentPos; protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void paintEvent(QPaintEvent *event); void enterEvent(QEvent *event); void leaveEvent(QEvent *event); void keyPressEvent(QKeyEvent *event); public: PieDialog(QWidget *parent = 0); }; #endif // PIEDIALOG_H |
piedialog.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
#include "piedialog.h" #include <QMouseEvent> #include <QPainter> #include <QtMath> PieDialog::PieDialog(QWidget *parent /* = 0 */) : QDialog(parent) { m_Color[0] = Qt::red; m_Color[1] = Qt::green; m_Color[2] = Qt::blue; m_Color[3] = Qt::cyan; m_Color[4] = Qt::magenta; m_Color[5] = Qt::yellow; m_Color[6] = Qt::darkYellow; m_Color[7] = Qt::darkRed; m_Color[8] = Qt::darkGreen; m_Color[9] = Qt::darkCyan; // qMemSet(m_Result, 0, sizeof(m_Result)); Qt5废弃 memset(m_Result, 0, sizeof(m_Result)); setWindowTitle("Pie Dialog"); setFixedSize(400, 300); //让程序背景透明 setWindowFlags( Qt::FramelessWindowHint ); setAttribute(Qt::WA_TranslucentBackground, true); } void PieDialog::mousePressEvent(QMouseEvent *event) { //按住左键可以托动窗口 if(event->button() == Qt::LeftButton) { m_CurrentPos = event->globalPos() - frameGeometry().topLeft(); event->accept(); } QDialog::mousePressEvent(event); } void PieDialog::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() && Qt::LeftButton) { move(event->globalPos() - m_CurrentPos); event->accept(); } QDialog::mouseMoveEvent(event); } void PieDialog::keyPressEvent(QKeyEvent *event) { //按数字键1-0相当于投票 for(int i=0; i<10; i++) { if( Qt::Key_0+i == event->key() ) { m_Result[i]++; break; } } update(); QDialog::keyPressEvent(event); } void PieDialog::paintEvent(QPaintEvent *event) { QPainter painter(this); //反走样 painter.setRenderHint(QPainter::Antialiasing, true); int cy = 10; //先画出颜色图解 for(int i=0; i<10; i++) { painter.setBrush( m_Color[i] ); painter.drawRect(320, cy, 30, 20); painter.drawText( QPoint(360, cy+15), QString::number(i) ); cy += 28; } painter.setPen( QPen(Qt::black, 1) ); const int FULL_CIRCLE = 5760; const int RADIUS = 140; QRect rect(10, 10, 280, 280); int count = 0; for(int i=0; i<10; i++) { count += m_Result[i]; } //如果还没有投过票,那就先画一个白色的圆形 if( 0 == count ) { painter.setBrush( Qt::white ); painter.drawEllipse(rect); return; } int pos = 0; int angle; for(int i=0; i<10; i++) { if( 0 == m_Result[i] ) continue; painter.setBrush( m_Color[i] ); double persent = (double)m_Result[i] / count; angle = FULL_CIRCLE * persent; //画出各个对应的扇形 double abc = 3.14 * 2 * (double)(pos + angle/2) / FULL_CIRCLE; double tx = 100 * qCos(abc) + 10 + RADIUS; double ty = -100 * qSin(abc) + 10 + RADIUS; painter.drawPie(rect, pos, angle); //在扇形上写注释(投票数和百分比) QString temp; temp.sprintf(" (%d) ", m_Result[i]); painter.drawText(tx-20, ty-10, temp); temp.sprintf("%0.1lf%%", persent*100); painter.drawText(tx-20, ty, temp); pos += angle; } } void PieDialog::leaveEvent(QEvent *event) { //鼠标离开窗口时是普通的指针 setCursor(Qt::ArrowCursor); } void PieDialog::enterEvent(QEvent *event) { //鼠标留在窗口上时是一个手指 setCursor(Qt::PointingHandCursor); } |
发表评论
要发表评论,您必须先登录。