3d pie chart
方法一:
目前实现效果,就是用drawPie函数分别画上下间距相同并且startAgl和spanAgl相同的两组扇形(颜色可根据显示设置),请看如下效果图:
很明显这样还是不够的,其中所指位置是需要修补的区域,利用drawPolygon或者drawRect函数画所指区域即可实现修补。具体修补区域的每个点的坐标,可根据椭圆的参数方程x=acost,y=bsint(a,b分别为长短半径,t为离心角)和各个扇形的startAgl,spanAgl算出,修补后的效果图如下图所示:
这样,即可实现3d
静态饼状图效果。
部分代码如下(测试用的,写的很乱:) ):
void Myclass::paintEvent(QPaintEvent *event)
{
// test 3D pie
QPainter painter;
painter.begin(this);
painter.setRenderHint(QPainter::Antialiasing, true); // 设置边缘光滑
const int iRectX = 300; // left pie pos
const int iRectY = 300;
const int iRectW = 280;
const int iRectH = 200;
const double pi = 3.1415926;
const int iSpanRed = 270;
const int iSpanAglGreen = 15;
const int iSpanAglBlue = 30;
const int iSpanAglYellow = 45;
const int iStartRed = 60;
const int iStartAglGreen = -(360-iSpanRed-iStartRed);
const int iStartAglBlue = -(-iStartAglGreen-iSpanAglGreen);
const int iStartAglYellow = iStartAglBlue + iSpanAglYellow;
// painter pie
QRect rect(iRectX, iRectY, iRectW, iRectH); // 左下方扇形
QRect rectUp(iRectX, iRectY-20, iRectW, iRectH); // 左上方扇形
QRect rectRt(iRectX+20, iRectY, iRectW, iRectH); // 右下方扇形
QRect rectRtUp(iRectX+20, iRectY-20, iRectW, iRectH); // 右上方扇形
int startAngleRed = iStartRed * 16;
int spanAngleRed = iSpanRed * 16;
int startAngleGreen = iStartAglGreen * 16;
int spanAngleGreen = iSpanAglGreen * 16;
int startAngleBlue = iStartAglYellow * 16;
int spanAngleBlue = iSpanAglBlue * 16;
int startAngleYellow = iStartAglBlue * 16;
int spanAngleYellow = iSpanAglYellow * 16;
/// 修补用
// 下方紅色扇形中心点位置
int x0 = iRectX + iRectW/2;
int y0 = iRectY + iRectH/2;
int posx = x0 + (int)iRectW * (cos((360 - iStartRed - iSpanRed)*pi/180)) / 2;
int posy = y0 + (int)iRectH * (sin((360 - iStartRed - iSpanRed)*pi/180)) / 2;
int posx_1 = x0 + (int)iRectW * (cos(-iStartRed*pi/180)) / 2;
int posy_1 = y0 + (int)iRectH * (sin(-iStartRed*pi/180)) / 2;
int posx_2 = x0 + (int)iRectW * (cos(-iStartAglBlue*pi/180)) / 2;
int posy_2 = y0 + (int)iRectH * (sin(-iStartAglBlue*pi/180)) / 2;
QPoint point_1(iRectX + iRectW/2 + 20, iRectY + iRectH/2); // down
QPoint point_2(iRectX + iRectW/2 + 20, iRectY + iRectH/2 - 20);// up
QPoint point_3(posx + 20, posy);
QPoint point_4(posx + 20, posy - 20);
QPoint points[4] = {point_1, point_2, point_4, point_3}; // 修补切面平行四边形位置
QPoint point_5(posx_2 + 20, posy_2);
QPoint point_6(posx_2 + 20, posy_2 - 20);
QPoint pots[4] = {point_3, point_4, point_6, point_5}; // 修补弧面平行四边形
/// painter pie
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::darkRed);
painter.drawPie(rect, startAngleRed, spanAngleRed); // 左下方扇形
// 右下方扇形
painter.setBrush(Qt::darkBlue);
painter.drawPie(rectRt, startAngleBlue, spanAngleBlue);
painter.setBrush(Qt::darkYellow);
painter.drawPie(rectRt, startAngleYellow, spanAngleYellow);
painter.setBrush(Qt::darkGreen);
painter.drawPie(rectRt, startAngleGreen, spanAngleGreen);
//
painter.setBrush(QColor(100, 255, 0, 255));
painter.drawPolygon(points, 4);// 修补切面平行四边形
painter.setBrush(Qt::darkGreen);
painter.drawPolygon(pots, 4); // 修补弧面平行四边形
painter.setBrush(Qt::darkRed); // 修补四方形
painter.drawRect(posx-20, posy-20, 20, 20); // 下方四邊形
painter.drawRect(posx_1-20, posy_1-20, 20, 20); // 上方四邊形
// 左上方扇形
painter.setPen(Qt::black);
painter.setBrush(Qt::red);
painter.drawPie(rectUp, startAngleRed, spanAngleRed);
// 右上方扇形
painter.setBrush(Qt::blue);
painter.drawPie(rectRtUp, startAngleBlue, spanAngleBlue);
painter.setBrush(Qt::yellow);
painter.drawPie(rectRtUp, startAngleYellow, spanAngleYellow);
painter.setBrush(Qt::green);
painter.drawPie(rectRtUp, startAngleGreen, spanAngleGreen);
painter.end();
}
现说第二种方法:
用qt的drawpie画, 在qt里面painter事件是按单位像素画的 要是设饼状图厚度为20像素,循环20次即可,画20个扇形,速度很快,这样就不需要修补了,并且可以改变每个扇形的比例和扇形个数
我做了个类,留有接口,调用只需传相应参数即可(当然根据需求可以自己添加接口喽!):
Draw3dPieChart.h
class CDraw3dPieChart : public QWidget
{
Q_OBJECT
public:
CDraw3dPieChart(QWidget *parent = 0);
public:
~CDraw3dPieChart(void);
public:
void setPiePos(int iPosX, int iPosY);
void setPieSize(int iWidth, int iHeight);
void setPiePerCent(QList lstPercent);
void setChartDepth(int iDepth);
void setChartDistance(int iDistence);// the distance of left and right???? 实现小部分扇形插入效果
void paintEvent(QPaintEvent *event); // override
private:
int m_iPosX;
int m_iPosY;
int m_iWidth;
int m_iHeight;
int m_iDepth;
int m_iDistence;
QList m_lstPercent;
QList m_lstSpanAgl;
QList m_lstStartAgl;
};
Draw3dPieChart.cpp
#include "Draw3dPieChart.h"
#include
/*--------------------------------------------------------------------------*/
/*-------------------------- Constant Definition ---------------------------*/
/*--------------------------------------------------------------------------*/
const QColor cstDownPieColor[7] = {
QColor(Qt::darkRed),
QColor(Qt::darkBlue),
QColor(Qt::darkYellow),
QColor(Qt::darkGreen),
QColor(Qt::darkCyan),
QColor(Qt::darkGray),
QColor(Qt::darkMagenta)
};
const QColor cstUpPieColor[7] = {
QColor(Qt::red),
QColor(Qt::blue),
QColor(Qt::yellow),
QColor(Qt::green),
QColor(Qt::cyan),
QColor(Qt::gray),
QColor(Qt::magenta)
}; //这里我定义了七种颜色,最大设为七块
CDraw3dPieChart::CDraw3dPieChart(QWidget *parent)
:QWidget(parent)
{
IFPRINTF("CDraw3dPieChart::CDraw3dPieChart");
NEWOBJECT("CDraw3dPieChart");
m_iPosX = 0;
m_iPosY = 0;
m_iWidth = 0;
m_iHeight = 0;
m_iDepth = 0;
m_iDistence = 0;
m_lstPercent.clear();
m_lstSpanAgl.clear();
m_lstStartAgl.clear();
setFixedSize(929, 530);
OFPRINTF("CDraw3dPieChart::CDraw3dPieChart")
}
CDraw3dPieChart::~CDraw3dPieChart(void)
{
IFPRINTF("CDraw3dPieChart::~CDraw3dPieChart");
DELOBJECT("CDraw3dPieChart");
m_lstPercent.clear();
m_lstSpanAgl.clear();
m_lstStartAgl.clear();
OFPRINTF("CDraw3dPieChart::~CDraw3dPieChart");
}
void CDraw3dPieChart::setPiePos(int iPosX, int iPosY)
{
IFPRINTF("CDraw3dPieChart::setPiePos");
m_iPosX = iPosX;
m_iPosY = iPosY;
OFPRINTF("CDraw3dPieChart::setPiePos");
}
void CDraw3dPieChart::setPieSize(int iWidth, int iHeight)
{
IFPRINTF("CDraw3dPieChart::setPieSize");
m_iWidth = iWidth;
m_iHeight = iHeight;
OFPRINTF("CDraw3dPieChart::setPieSize");
}
void CDraw3dPieChart::setChartDepth(int iDepth)
{
IFPRINTF("CDraw3dPieChart::setChartDepth");
m_iDepth = iDepth;
OFPRINTF("CDraw3dPieChart::setChartDepth");
}
void CDraw3dPieChart::setChartDistance(int iDistence)
{
IFPRINTF("CDraw3dPieChart::setChartDistance");
m_iDistence = iDistence;
OFPRINTF("CDraw3dPieChart::setChartDistance");
}
void CDraw3dPieChart::setPiePerCent(QList lstPercent)
{
IFPRINTF("CDraw3dPieChart::setPiePerCent");
m_lstPercent = lstPercent;
OFPRINTF("CDraw3dPieChart::setPiePerCent");
}
void CDraw3dPieChart::paintEvent(QPaintEvent *event)
{
IFPRINTF("CDraw3dPieChart::paintEvent");
Q_UNUSED(event);
QPainter painter;
painter.begin(this);
m_lstSpanAgl.clear();
m_lstStartAgl.clear();
m_lstStartAgl.append(60);
if (m_lstPercent.size() <= 0)
{
return;
}
for (int i = 0; i
{
m_lstSpanAgl.append(ceil(360*m_lstPercent.at(i)));
if (i == 0)
{
continue;
}
m_lstStartAgl.append(m_lstSpanAgl.at(i-1) + m_lstStartAgl.at(i-1));
}
painter.setRenderHint(QPainter::Antialiasing, true); //设置平滑
painter.setPen(Qt::NoPen);
//下部分循环m_iDepth次
for (int i = 0; i
{
QRect rectDown(m_iPosX, m_iPosY-i, m_iWidth, m_iHeight);
for (int j = 0; j
{
painter.setBrush(cstDownPieColor[j]);
painter.drawPie(rectDown, m_lstStartAgl.at(j)*16, m_lstSpanAgl.at(j)*16);
}
}
//最上部分画一次(不同颜色)
QRect rectUp(m_iPosX, m_iPosY-m_iDepth, m_iWidth, m_iHeight);
for (int i = 0; i
{
painter.setBrush(cstUpPieColor[i]);
painter.drawPie(rectUp, m_lstStartAgl.at(i)*16, m_lstSpanAgl.at(i)*16);
}
painter.end();
OFPRINTF("CDraw3dPieChart::paintEvent");
}
例如如此调用:
QList lstPercent; //扇形个数与每个扇形的百分比
lstPercent.append(0.1);
lstPercent.append(0.3);
lstPercent.append(0.2);
lstPercent.append(0.4);
CDraw3dPieChart *draw3dPie = new CDraw3dPieChart(this);
draw3dPie->setPiePos(200, 200);
draw3dPie->setPieSize(280, 200);
draw3dPie->setPiePerCent(lstPercent);
draw3dPie->setChartDepth(20);
效果:
根据lstPercent传的个数和比例,可以改变比例大小和扇形个数
ok!!!!
推荐阅读
-
注:根据Qt小神童的视频教程改编概论:利用最新的Qt5.1.1在windows下开发的一个小的时钟程序,有指针与表盘。1.Qtforwindows开发环境最新的Qt已经集 ...
[详细]
蜡笔小新 2023-10-17 09:42:19
-
本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ...
[详细]
蜡笔小新 2023-12-14 16:06:38
-
-
本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ...
[详细]
蜡笔小新 2023-12-13 16:37:19
-
本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ...
[详细]
蜡笔小新 2023-12-13 14:17:11
-
本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ...
[详细]
蜡笔小新 2023-12-13 09:08:55
-
重启Oracle数据库重启Oracle数据库包括启动Oracle数据库服务进程和启动Oracle数据库两步,大家继续往下看。按照《【Oracle】什么?作为DBA ...
[详细]
蜡笔小新 2023-10-16 22:31:42
-
建表语句:DROPTABLEIFEXISTSgoods;CREATETABLEgoods(store_cdint4NOTNULL,good_cdvarchar(50 ...
[详细]
蜡笔小新 2023-10-16 12:33:57
-
本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ...
[详细]
蜡笔小新 2023-12-14 17:15:38
-
本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ...
[详细]
蜡笔小新 2023-12-14 14:37:52
-
本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ...
[详细]
蜡笔小新 2023-12-14 12:36:28
-
本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ...
[详细]
蜡笔小新 2023-12-14 12:03:27
-
本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ...
[详细]
蜡笔小新 2023-12-13 12:01:03
-
Thisissuewasoriginallyopenedbyashashicorp/terraform#5664.Itwasmigratedhe ...
[详细]
蜡笔小新 2023-10-16 19:31:15
-
本人Eclipse版本是”eclipse-jee-kepler-SR2-win32-x86_64“昨天因为换电脑,所以重装了一下软件,装好eclipse ...
[详细]
蜡笔小新 2023-10-16 16:49:10
-
HTCRider/X515E/EVO4G+手机存储(SD卡)中各个文件夹功能说明 HTCRider/X515E/EVO4G+ 1、.android_s ...
[详细]
蜡笔小新 2023-10-16 10:15:14
-
mobiledu2502861323
这个家伙很懒,什么也没留下!