QT:浮动的饼状统计图(自绘不规则窗口)

    昨天在玩手机游戏时,见到一个游戏的饼状投票统计图很漂亮,所以我今天也花了一个下午来实现了一个类似的程序娱乐一下,呵呵。

思路:
1:将窗体设为Qt::FramelessWindowHint和Qt::WA_TranslucentBackground(去掉标题栏,背景透明)。
2:重载程序的鼠标事件(移动程序)和键盘事件(模拟投票和退出)。
3:根据投票结果,在paintEvent函数中画几个扇形和其他东西。

操作说明:
1:按数字键0-9模拟投票。

2:按ESC键退出程序。


运行时截图(浅绿色的是桌面背景)

QT:浮动的饼状统计图(自绘不规则窗口)_第1张图片


源代码:

#include 

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);
};

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));
	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);    
}    

#include "main.moc"    

int main(int argc, char *argv[])    
{    
	QApplication app(argc, argv);    
	PieDialog *dialog = new PieDialog;    
	dialog->show();    
	return app.exec();    
}    


你可能感兴趣的:(QT小例子)