天天看點

Qt實作3D餅圖

實作思路:采取畫多個圓進行疊加實作3D的效果(參考另外的一個部落格内容,忘記具體是哪個了

Qt實作3D餅圖

)。

效果1:

Qt實作3D餅圖

代碼實作:

void CPieWidget::drawDefault3DPie( QPainter *painter )
{
	qreal sum = getSumValue();
	int radius = m_radius; //直徑
	//QRect rect = m_pierect;//(w/2-radius/2,h/2-radius/2,radius,radius);

	painter->save();
	QPoint centerp = m_pierect.center();

	QTransform tr;
	tr.translate(centerp.x(),centerp.y());
	tr.rotate(-20,Qt::ZAxis);
	tr.rotate(0,Qt::YAxis);

	painter->setTransform(tr);
	QRect rect(-radius/2,-radius/2,radius,radius);

	//畫底圖
	int dep = 20/*radius/30*/;
	QPen pen;
	pen.setWidthF(0.2);
	painter->setPen(pen);
	//painter->setPen(Qt::NoPen);
	QStringList keylist = m_datamap.keys();
	for (int j = 0 ; j < dep; ++j)
	{
		qreal index = 30;  //啟始位置
		int colorindex = 0;
		for (int i = 0; i < keylist.count(); ++i)
		{
			qreal v = m_datamap.value(keylist.at(i));
			v =v/sum*(360);
			QRect newrect = rect;
			if (m_explodedindex == i || m_isexploded)
			{
				QPoint newcenter = newrect.center();
				int midangel = index+v/2;
				QPoint tp = getMovePoint(midangel);
				newcenter += tp;
				newrect.moveCenter(newcenter);
			}
			QPoint cp = newrect.center() + QPoint(j/2,-j);
			newrect.moveCenter(cp);

			QPoint centerPoint = newrect.center();
			QColor firstColor = m_colorlist.at(colorindex);
			QRadialGradient firstGradient(centerPoint, radius/2);
			if (j == 19)
			{
				firstGradient.setColorAt(0, firstColor.lighter(120));
				firstGradient.setColorAt(1.0, firstColor.lighter(100));
			}
			else
				firstGradient.setColorAt(1.0, firstColor.dark(150));
			painter->setBrush(firstGradient);

			painter->drawPie(newrect, index * 16, v * 16);
			index+=v;		
			colorindex++;
			if (colorindex==m_colorlist.count())
			{
				colorindex = 0;
			}
		}
	}	
	painter->restore();

	
}
           

效果2:

Qt實作3D餅圖

代碼如下:

void CPieWidget::drawDount3DPie( QPainter *painter )
{
	qreal sum = getSumValue();
	int radius = m_radius; //直徑
	QPoint centerp = m_pierect.center();

	painter->save();
	QTransform tr;
	tr.translate(centerp.x(),centerp.y());
	tr.rotate(-20,Qt::ZAxis);
	tr.rotate(0,Qt::YAxis);

	painter->setTransform(tr);
	//QRect rect(w/2-radius/2,h/2-radius/2,radius,radius);
	QRect rect(-radius/2,-radius/2,radius,radius);

	//畫底圖
	int dep = 20/*radius/30*/;
	QPen pen;
	pen.setWidthF(0.2);
	painter->setPen(pen);
	painter->setPen(Qt::NoPen);
	QStringList keylist = m_datamap.keys();
	for (int j = 0 ; j < dep; ++j)
	{
		qreal index = 30;  //啟始位置
		int colorindex = 0;
		for (int i = 0; i < keylist.count(); ++i)
		{
			qreal v = m_datamap.value(keylist.at(i));
			v =v/sum*(360);
			QRect newrect = rect;
			if (m_explodedindex == i || m_isexploded)
			{
				QPoint newcenter = newrect.center();
				int midangel = index+v/2;
				QPoint tp = getMovePoint(midangel);
				newcenter += tp;
				newrect.moveCenter(newcenter);
			}
			QPoint cp = newrect.center() + QPoint(j/2,-j);
			newrect.moveCenter(cp);

			QPoint centerPoint = newrect.center();
			QColor firstColor = m_colorlist.at(colorindex);
			QRadialGradient firstGradient(centerPoint, radius/2);
			firstGradient.setColorAt(0, Qt::transparent);
			firstGradient.setColorAt(0.6, Qt::transparent);
			if (j == 19)
			{
				firstGradient.setColorAt(0.61, firstColor.lighter(120));
				firstGradient.setColorAt(1.0, firstColor.lighter(100));
			}
			else
			{
				firstGradient.setColorAt(0.61, firstColor.dark(120));
				firstGradient.setColorAt(1.0, firstColor.dark(150));
			}
			painter->setBrush(firstGradient);

			painter->drawPie(newrect, index * 16, v * 16);
			index+=v;		
			colorindex++;
			if (colorindex==m_colorlist.count())
			{
				colorindex = 0;
			}
		}
	}	
	painter->restore();
}
           

相關變量說明

QHash<QString,float> m_datamap;

QList<QColor> m_colorlist;

QRect m_pierect;

QRect m_legendrect;

int m_radius;

///

這種方式實作可能會影響效率,因為循環畫了多次。

Qt

繼續閱讀