山前大桥下,有一个傻瓜。一枚小学生,幽居荒山中。养了一群狗,还有一只猫。喜欢搞编程,缺钱打零工。数理史皆通,法文记心中。下厨会做饭,挥毫能舞文。
注意:文中代码与下面图像不是同一套代码,下面的图片为最终的运行效果图,由于代码非常长,而受限于篇幅限制示例中的代码为开发之初测试代码,原理相同。用于学习目的
PS:代码请移步QT,C++实现的天干地支八卦图源代码-C++文档类资源-CSDN文库https://download.csdn.net/download/wastelandboy/81443268
先上一张图。视频稍后插入
视频
20220219-132217
正文开始,首先是头文件代码
#include <QWidget>
#include <QOpenGLWidget>
class QTimer;
class Qiankunmap : public QWidget
{
Q_OBJECT
public:
explicit Qiankunmap(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
private:
void drawYinYangFish(QPainter *painter, qreal radius);
void drawGua(QPainter *painter, qreal radius);
void drawGuaCharacter(QPainter *painter, qreal radius_outer, qreal radius_inner);
void drawCircle(QPainter *painter, qreal radius, const QColor &color, qreal penWidth);
void draw24SolarTerms(QPainter *painter, qreal radius_outer, qreal radius_inner);
void drawTianGanDiZhi(QPainter *painter, qreal radius_outer, qreal radius_inner);
void drawDiZhiWith5Elements(QPainter *painter, qreal radius_outer, qreal radius_inner);
void drawTianGanWith5Elements(QPainter *painter, qreal radius_outer, qreal radius_inner);
void drawOneEighthSeperator(QPainter *painter, qreal radius1, qreal radius2);
void drawOneTwentyFourthSeperator(QPainter *painter, qreal radius1, qreal radius2);
void drawQuarterSeperator(QPainter *painter, qreal radius1, qreal radius2);
private:
QTimer *timer_;
qreal degree_ = 0;
private slots:
void onTimer();
};
源文件全部代码如下:
#include "Qiankunmap.h"
#include <QtDebug>
#include <QPainter>
#include <QPainterPath>
#include <QStaticText>
#include <QHoverEvent>
#include <QTimer>
#include <cmath>
static auto angle_8_1 = 360.0 / 8.0;
static auto angle_24_1 = 360.0 / 24.0;
static auto angle_32_1 = 360.0 / 32.0;
//渐变背景颜色结构体
typedef struct GRADIENTCOLOR_DATAS_{
double fBkgndAngleVal; //渐变背景角度从0到1
QColor cBkgndAngleClr; //渐变背景当前角度颜色
}GRADIENTCOLOR_DATAS,*PGRADIENTCOLOR_DATAS;
static QList<std::u16string> sTianGanChar ={u"乾",u"巽",u"坎",u"艮",u"坤",u"震",u"离",u"兑"};
static QList<std::u16string> sSolarsTerms={u"冬至",u"小寒",u"大寒",u"立春",u"雨水",u"惊蛰",u"春分",u"清明",u"谷雨",u"立夏",u"小满",u"芒种",
u"夏至",u"小暑",u"大暑",u"立秋",u"处暑",u"白露",u"秋分",u"寒露",u"霜降",u"立冬",u"小雪",u"大雪"};
static QList<std::u16string> sElementsTwo={u"丙丁火",u"已坤土",u"庚辛金",u"乾阳金",u"壬癸水",u"戊艮土",u"甲乙木",u"巽风木"};
static QList<std::u16string> sElementsOne={u"午火",u"未土",u"申金",u"酉金",u"戌土",u"亥水",u"子水",u"丑土",u"寅木",u"卯木",u"辰土",u"巳水"};
static QList<std::u16string> sTianGanDiz={u"子",u"壬",u"丑",u"癸",u"寅",u"艮",u"卯",u"甲",u"辰",u"乙",u"巳",u"巽",u"午",u"丙",u"未",u"丁",u"申",u"坤",u"酉",u"庚",u"戌",u"辛",u"亥",u"乾"};
static QList<GRADIENTCOLOR_DATAS> vBkgColorsList = {{0, QColor(35, 40, 3, 255)},{0.16, QColor(136, 106, 22, 255)},{0.225, QColor(166, 140, 41, 255)},
{0.285, QColor(204, 181, 74, 255)},{0.345, QColor(235, 219, 102, 255)},{0.415, QColor(245, 236, 112, 255)},
{0.52, QColor(209, 190, 76, 255)},{0.57, QColor(187, 156, 51, 255)},{0.635, QColor(168, 142, 42, 255)},
{0.695, QColor(202, 174, 68, 255)},{0.75, QColor(218, 202, 86, 255)},{0.815, QColor(208, 187, 73, 255)},
{0.88, QColor(187, 156, 51, 255)},{0.935, QColor(137, 108, 26, 255)},{1, QColor(35, 40, 3, 255)}}; //渐变背景颜色集合
Qiankunmap::Qiankunmap(QWidget *parent)
: QWidget(parent)
{
resize(600, 600);
timer_ = new QTimer(this);
connect(timer_, &QTimer::timeout, this, &Qiankunmap::onTimer);
timer_->start(30);
}
void Qiankunmap::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter painter(this);
painter.fillRect(rect(), Qt::white);
painter.setRenderHints(QPainter::Antialiasing);
// 移动当前的坐标系到绘制的中心,这样便于坐标计算
painter.translate(QPointF(width()/ 2.0 , height() / 2.0));
auto radius = std::min(this->width(), this->height()) / 2.0;
// 从外层到内的圆环占据整个绘制的比例
auto radius_1 = radius * (300.0 - 10.000) / 300.0;
auto radius_2 = radius * (300.0 - 60.00) / 300.0;
auto radius_3 = radius * (300.0 - 120.0) / 300.0;
auto radius_4 = radius * (300.0 - 150.0) / 300.0;
auto radius_5 = radius * (300.0 - 190.0) / 300.0;
auto radius_6 = radius * (300.0 - 220.0) / 300.0;
auto radius_7 = radius * (300.0 - 250.0) / 300.0; // 鱼圆圈
painter.save();
painter.setPen(Qt::NoPen);
QConicalGradient coneGradient(0, 0, 180.0);
int sCount=vBkgColorsList.count();
for(int s=0;s<sCount;s++){
coneGradient.setColorAt(vBkgColorsList[s].fBkgndAngleVal,vBkgColorsList[s].cBkgndAngleClr);
}
painter.setBrush(coneGradient);
painter.drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter.restore();
drawYinYangFish(&painter, radius_7);
drawGua(&painter, radius_6);
drawGuaCharacter(&painter, radius_5, radius_6);
drawCircle(&painter, radius_5, QColor(0x808000), 3.0);
drawTianGanWith5Elements(&painter, radius_4, radius_5);
drawCircle(&painter, radius_4, QColor(0x808000), 3.0);
drawDiZhiWith5Elements(&painter, radius_3, radius_4);
drawCircle(&painter, radius_3, QColor(0xDC143C), 3.0);
drawTianGanDiZhi(&painter, radius_2, radius_3);
drawCircle(&painter, radius_2, QColor(Qt::black), 2.0);
draw24SolarTerms(&painter, radius_1, radius_2);
drawCircle(&painter, radius_1, QColor(0x834447), 6.0);
drawOneEighthSeperator(&painter, radius_1, radius_7);
drawOneTwentyFourthSeperator(&painter, radius_1, radius_3);
drawQuarterSeperator(&painter, radius_3, radius_4);
}
void Qiankunmap::drawYinYangFish(QPainter *painter, qreal radius)
{
auto diameter = 2.0 * radius;
painter->save();
painter->setPen(Qt::black);
painter->setBrush(Qt::black);
painter->drawEllipse(QRectF(-radius, -radius, diameter, diameter));
painter->restore();
// white fish head
auto fishHeadRadius = radius / 2.0f;
QPainterPath path(QPointF(0.0f, -radius));
path.arcTo(QRectF(-radius, -radius, diameter, diameter), 90.0, 180.0);
path.arcTo(QRectF(-fishHeadRadius, 0.0, radius, radius), -90.0, -180.0);
path.arcTo(QRectF(-fishHeadRadius, -radius, radius, radius), -90.0, 180.0);
painter->save();
painter->setPen(QPen(QColor(Qt::black), 2.0));
painter->drawPath(path); // he he
painter->fillPath(path, Qt::white);
painter->restore();
// white fish eye
auto fishEyeWidth = radius / 2.5f;
painter->save();
painter->setPen(QPen(QBrush(Qt::black), fishEyeWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPoint(QPointF(0.0f, -radius / 2.0f));
painter->restore();
// black fish eye
painter->save();
painter->setPen(QPen(QBrush(Qt::white), fishEyeWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPoint(QPointF(0.0f, radius / 2.0f));
painter->restore();
}
void Qiankunmap::drawGua(QPainter *painter, qreal radius)
{
painter->save();
painter->rotate(degree_);
auto penWidth = 4.0;
static auto spacerAngle = angle_8_1 / 8.0;
static auto rightStartAngle = (angle_8_1 + angle_8_1 / 2.0 + spacerAngle) * 16;
static auto leftStartAngle = (90.0 + spacerAngle) * 16;
static auto spanAngleFull = (angle_8_1 - 2 * spacerAngle) * 16;
static auto spanAngleHalf = (angle_8_1 / 2.0 - 2 * spacerAngle) * 16;
auto drawer = [=](qreal angle, std::tuple<bool, QColor, QColor> top, std::tuple<bool, QColor, QColor> middle, std::tuple<bool, QColor, QColor> bottom){
painter->save();
painter->rotate(angle);
// top
if(std::get<0>(top)){
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(top)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawArc(QRectF(-radius, -radius, 2 * radius, 2 * radius),
rightStartAngle,
spanAngleFull);
painter->restore();
}else{
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(top)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawArc(QRectF(-radius, -radius, 2 * radius, 2 * radius),
rightStartAngle,
spanAngleHalf);
painter->restore();
painter->save();
painter->setPen(QPen(QBrush(std::get<2>(top)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawArc(QRectF(-radius, -radius, 2 * radius, 2 * radius),
leftStartAngle,
spanAngleHalf);
painter->restore();
}
// middle
auto radius_temp = radius - 2.0 * penWidth;
if(std::get<0>(middle)){
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(middle)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawArc(QRectF(-radius_temp, -radius_temp, 2 * radius_temp, 2 * radius_temp),
rightStartAngle,
spanAngleFull);
painter->restore();
}else{
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(middle)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawArc(QRectF(-radius_temp, -radius_temp, 2 * radius_temp, 2 * radius_temp),
rightStartAngle,
spanAngleHalf);
painter->restore();
painter->save();
painter->setPen(QPen(QBrush(std::get<2>(middle)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawArc(QRectF(-radius_temp, -radius_temp, 2 * radius_temp, 2 * radius_temp),
leftStartAngle,
spanAngleHalf);
painter->restore();
}
// bottom
radius_temp = radius - 4.0 * penWidth;
if(std::get<0>(bottom)){
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(bottom)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawArc(QRectF(-radius_temp, -radius_temp, 2 * radius_temp, 2 * radius_temp),
rightStartAngle,
spanAngleFull);
painter->restore();
}else{
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(bottom)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawArc(QRectF(-radius_temp, -radius_temp, 2 * radius_temp, 2 * radius_temp),
rightStartAngle,
spanAngleHalf);
painter->restore();
painter->save();
painter->setPen(QPen(QBrush(std::get<2>(bottom)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawArc(QRectF(-radius_temp, -radius_temp, 2 * radius_temp, 2 * radius_temp),
leftStartAngle,
spanAngleHalf);
painter->restore();
}
painter->restore(); // restore for rotate
};
/*-------------------------
* 离中虚
* */
drawer(angle_8_1 * 0.0,
std::make_tuple(true, QColor(0xDC143C), QColor()),
std::make_tuple(false, QColor(0xFFFF00), QColor(0xFFD700)),
std::make_tuple(true, QColor(0xF1D24E), QColor()));
/*-------------------------
* 坤六断
* */
drawer(angle_8_1 * 1.0,
std::make_tuple(false, QColor(0xBC211E), QColor(0xEAB529)),
std::make_tuple(false, QColor(0xADFF2F), QColor(0x7CFC00)),
std::make_tuple(false, QColor(0xEEE8AA), QColor(0xF0E68C)));
/*-------------------------
* 兑上缺
* */
drawer(angle_8_1 * 2.0,
std::make_tuple(false, QColor(0x40E0D0), QColor(0x7FFFAA)),
std::make_tuple(true, QColor(0x00FA9A), QColor()),
std::make_tuple(true, QColor(0x00FF7F), QColor()));
/*-------------------------
* 乾三连
* */
drawer(angle_8_1 * 3.0,
std::make_tuple(true, QColor(0x87CEFA), QColor()),
std::make_tuple(true, QColor(0x87CEEB), QColor()),
std::make_tuple(true, QColor(0x00BFFF), QColor()));
/*-------------------------
* 坎中满
* */
drawer(angle_8_1 * 4.0,
std::make_tuple(false, QColor(0xB0E0E6), QColor(0xB0E0E6)),
std::make_tuple(true, QColor(0x5F9EA0), QColor()),
std::make_tuple(false, QColor(0x008B8B), QColor(0x00CED1)));
/*-------------------------
* 艮覆碗
* */
drawer(angle_8_1 * 5.0,
std::make_tuple(true, QColor(0xBA55D3), QColor()),
std::make_tuple(false, QColor(0x9400D3), QColor(0x9932CC)),
std::make_tuple(false, QColor(0xBA55D3), QColor(0x9370DB)));
/*-------------------------
* 震仰盂
* */
drawer(angle_8_1 * 6.0,
std::make_tuple(false, QColor(0xDDA0DD), QColor(0xEE82EE)),
std::make_tuple(false, QColor(0xFF00FF), QColor(0xFF00FF)),
std::make_tuple(true, QColor(0xDA70D6), QColor()));
/*-------------------------
* 巽下断
* */
drawer(angle_8_1 * 7.0,
std::make_tuple(true, QColor(0xFF69B4), QColor()),
std::make_tuple(true, QColor(0xFF1493), QColor()),
std::make_tuple(false, QColor(0xFFB6C1), QColor(0xFFC0CB)));
painter->restore();
}
void Qiankunmap::drawGuaCharacter(QPainter *painter,
qreal radius_outer,
qreal radius_inner)
{
auto height = radius_outer - radius_inner;
auto fontSizePixel = height * 3.0 / 5.0;
auto drawer = [=](qreal degree, const QString &character, const QColor &color = QColor()){
painter->save();
painter->rotate(degree);
auto font = painter->font();
font.setPixelSize(fontSizePixel);
font.setFamily("KaiTi");
painter->setFont(font);
painter->setPen(color);
auto fm = painter->fontMetrics();
auto rect = fm.boundingRect(character);
painter->drawStaticText(-rect.width() / 2.0, -radius_outer + height * 1.0 / 5.0, QStaticText(character));
painter->restore();
};
drawer(angle_8_1 * 0.0, QString::fromStdU16String(sTianGanChar[0]) , QColor(0x48D1CC));
drawer(angle_8_1 * 1.0, QString::fromStdU16String(sTianGanChar[1]), QColor(0x00FF7F));
drawer(angle_8_1 * 2.0, QString::fromStdU16String(sTianGanChar[2]) , QColor(0x00BFFF));
drawer(angle_8_1 * 3.0, QString::fromStdU16String(sTianGanChar[3]), QColor(0x4682B4));
drawer(angle_8_1 * 4.0, QString::fromStdU16String(sTianGanChar[4]) , QColor(0x000080));
drawer(angle_8_1 * 5.0, QString::fromStdU16String(sTianGanChar[5]) , QColor(0xFFA500));
drawer(angle_8_1 * 6.0, QString::fromStdU16String(sTianGanChar[6]), QColor(0xF4A460));
drawer(angle_8_1 * 7.0, QString::fromStdU16String(sTianGanChar[7]), QColor(0xFF6347));
}
void Qiankunmap::drawCircle(QPainter *painter, qreal radius, const QColor &color, qreal penWidth)
{
painter->save();
painter->setPen(QPen(QBrush(color), penWidth));
painter->drawEllipse(QRectF(-radius, -radius, 2.0 * radius, 2.0 * radius));
painter->restore();
}
void Qiankunmap::draw24SolarTerms(QPainter *painter, qreal radius_outer, qreal radius_inner)
{
auto height = radius_outer - radius_inner;
auto fontSizePixel = height * 2.0 / 4.0;
auto drawer = [=](qreal degree, const QString &character){
painter->save();
painter->rotate(degree);
auto font = painter->font();
font.setPixelSize(fontSizePixel);
// font.setFamily("LiSu");
painter->setFont(font);
auto fm = painter->fontMetrics();
auto rect = fm.boundingRect(character);
painter->drawStaticText(-rect.width() / 2.0, -radius_outer + height * 1.0 / 4.0, QStaticText(character));
painter->restore();
};
drawer(angle_24_1 * 0.0, QString::fromStdU16String(sSolarsTerms[0]));
drawer(angle_24_1 * 1.0, QString::fromStdU16String(sSolarsTerms[1]));
drawer(angle_24_1 * 2.0, QString::fromStdU16String(sSolarsTerms[2]));
drawer(angle_24_1 * 3.0, QString::fromStdU16String(sSolarsTerms[3]));
drawer(angle_24_1 * 4.0, QString::fromStdU16String(sSolarsTerms[4]));
drawer(angle_24_1 * 5.0, QString::fromStdU16String(sSolarsTerms[5]));
drawer(angle_24_1 * 6.0, QString::fromStdU16String(sSolarsTerms[6]));
drawer(angle_24_1 * 7.0, QString::fromStdU16String(sSolarsTerms[7]));
drawer(angle_24_1 * 8.0, QString::fromStdU16String(sSolarsTerms[8]));
drawer(angle_24_1 * 9.0, QString::fromStdU16String(sSolarsTerms[9]));
drawer(angle_24_1 * 10.0, QString::fromStdU16String(sSolarsTerms[10]));
drawer(angle_24_1 * 11.0, QString::fromStdU16String(sSolarsTerms[11]));
drawer(angle_24_1 * 12.0, QString::fromStdU16String(sSolarsTerms[12]));
drawer(angle_24_1 * 13.0, QString::fromStdU16String(sSolarsTerms[13]));
drawer(angle_24_1 * 14.0, QString::fromStdU16String(sSolarsTerms[14]));
drawer(angle_24_1 * 15.0, QString::fromStdU16String(sSolarsTerms[15]));
drawer(angle_24_1 * 16.0, QString::fromStdU16String(sSolarsTerms[16]));
drawer(angle_24_1 * 17.0, QString::fromStdU16String(sSolarsTerms[17]));
drawer(angle_24_1 * 18.0, QString::fromStdU16String(sSolarsTerms[18]));
drawer(angle_24_1 * 19.0, QString::fromStdU16String(sSolarsTerms[19]));
drawer(angle_24_1 * 20.0, QString::fromStdU16String(sSolarsTerms[20]));
drawer(angle_24_1 * 21.0, QString::fromStdU16String(sSolarsTerms[21]));
drawer(angle_24_1 * 22.0, QString::fromStdU16String(sSolarsTerms[22]));
drawer(angle_24_1 * 23.0, QString::fromStdU16String(sSolarsTerms[23]));
}
void Qiankunmap::drawTianGanDiZhi(QPainter *painter, qreal radius_outer, qreal radius_inner)
{
auto height = radius_outer - radius_inner;
auto fontSizePixel = height * 2.0 / 4.0;
auto drawer = [=](qreal degree, const QString &character,const QColor &fontColor = QColor()){
painter->save();
painter->rotate(degree);
auto font = painter->font();
font.setPixelSize(fontSizePixel);
// font.setFamily("LiSu");
painter->setFont(font);
painter->setPen(QPen(fontColor));
auto fm = painter->fontMetrics();
auto rect = fm.boundingRect(character);
painter->drawStaticText(-rect.width() / 2.0, -radius_outer + height * 1.0 / 4.0, QStaticText(character));
painter->restore();
};
drawer(angle_24_1 * 0.0, QString::fromStdU16String(sTianGanDiz[0]), QColor(255,182,193));
drawer(angle_24_1 * 1.0, QString::fromStdU16String(sTianGanDiz[1]), QColor(255,192,203));
drawer(angle_24_1 * 2.0, QString::fromStdU16String(sTianGanDiz[2]), QColor(220,20,60));
drawer(angle_24_1 * 3.0, QString::fromStdU16String(sTianGanDiz[3]), QColor(0,255,127));
drawer(angle_24_1 * 4.0, QString::fromStdU16String(sTianGanDiz[4]), QColor(219,112,147));
drawer(angle_24_1 * 5.0, QString::fromStdU16String(sTianGanDiz[5]), QColor(255,105,180));
drawer(angle_24_1 * 6.0, QString::fromStdU16String(sTianGanDiz[6]), QColor(255,20,147));
drawer(angle_24_1 * 7.0, QString::fromStdU16String(sTianGanDiz[7]), QColor(199,21,133));
drawer(angle_24_1 * 8.0, QString::fromStdU16String(sTianGanDiz[8]), QColor(139,0,139));
drawer(angle_24_1 * 9.0, QString::fromStdU16String(sTianGanDiz[9]), QColor(70,130,180));
drawer(angle_24_1 * 10.0, QString::fromStdU16String(sTianGanDiz[10]), QColor(135,206,235));
drawer(angle_24_1 * 11.0, QString::fromStdU16String(sTianGanDiz[11]), QColor(173,216,230));
drawer(angle_24_1 * 12.0, QString::fromStdU16String(sTianGanDiz[12]), QColor(176,224,230));
drawer(angle_24_1 * 13.0, QString::fromStdU16String(sTianGanDiz[13]), QColor(95,158,160));
drawer(angle_24_1 * 14.0, QString::fromStdU16String(sTianGanDiz[14]), QColor(0,255,255));
drawer(angle_24_1 * 15.0, QString::fromStdU16String(sTianGanDiz[15]), QColor(0,128,128));
drawer(angle_24_1 * 16.0, QString::fromStdU16String(sTianGanDiz[16]), QColor(0,206,209));
drawer(angle_24_1 * 17.0, QString::fromStdU16String(sTianGanDiz[17]), QColor(72,209,204));
drawer(angle_24_1 * 18.0, QString::fromStdU16String(sTianGanDiz[18]), QColor(127,255,0));
drawer(angle_24_1 * 19.0, QString::fromStdU16String(sTianGanDiz[19]), QColor(255,140,0));
drawer(angle_24_1 * 20.0, QString::fromStdU16String(sTianGanDiz[20]), QColor(255,99,71));
drawer(angle_24_1 * 21.0, QString::fromStdU16String(sTianGanDiz[21]), QColor(0,255,0));
drawer(angle_24_1 * 22.0, QString::fromStdU16String(sTianGanDiz[22]), QColor(240,230,140));
drawer(angle_24_1 * 23.0, QString::fromStdU16String(sTianGanDiz[23]), QColor(127,255,0));
}
void Qiankunmap::drawDiZhiWith5Elements(QPainter *painter, qreal radius_outer, qreal radius_inner)
{
auto height = radius_outer - radius_inner;
auto fontSizePixel = height * 2.0 / 3.5;
auto drawer = [=](qreal degree, const QString &character,const QColor &fontColor = QColor()){
painter->save();
painter->rotate(degree);
auto font = painter->font();
font.setPixelSize(fontSizePixel);
// font.setFamily("LiSu");
painter->setFont(font);
painter->setPen(QPen(fontColor));
auto fm = painter->fontMetrics();
auto rect = fm.boundingRect(character);
painter->drawStaticText(-rect.width() / 2.0, -radius_outer + height * 1.0 / 4.0, QStaticText(character));
painter->restore();
};
drawer(angle_8_1 * 0.0, QString::fromStdU16String(sElementsOne[0]));
drawer(angle_8_1 * 0.5 + angle_32_1, QString::fromStdU16String(sElementsOne[1]));
drawer(angle_8_1 * 1.0 + angle_32_1, QString::fromStdU16String(sElementsOne[2]));
drawer(angle_8_1 * 2.0, QString::fromStdU16String(sElementsOne[3]));
drawer(angle_8_1 * 2.5 + angle_32_1, QString::fromStdU16String(sElementsOne[4]));
drawer(angle_8_1 * 3.0 + angle_32_1, QString::fromStdU16String(sElementsOne[5]));
drawer(angle_8_1 * 4.0, QString::fromStdU16String(sElementsOne[6]));
drawer(angle_8_1 * 4.5 + angle_32_1, QString::fromStdU16String(sElementsOne[7]));
drawer(angle_8_1 * 5.0 + angle_32_1, QString::fromStdU16String(sElementsOne[8]));
drawer(angle_8_1 * 6.0, QString::fromStdU16String(sElementsOne[9]));
drawer(angle_8_1 * 6.5 + angle_32_1, QString::fromStdU16String(sElementsOne[10]));
drawer(angle_8_1 * 7.0 + angle_32_1, QString::fromStdU16String(sElementsOne[11]));
}
void Qiankunmap::drawTianGanWith5Elements(QPainter *painter, qreal radius_outer, qreal radius_inner)
{
auto height = radius_outer - radius_inner;
auto fontSizePixel = height * 2.0 / 4.0;
auto drawer = [=](qreal degree, const QString &character,const QColor &fontColor = QColor()){
painter->save();
painter->rotate(degree);
auto font = painter->font();
font.setPixelSize(fontSizePixel);
// font.setFamily("LiSu");
painter->setFont(font);
painter->setPen(QPen(fontColor));
auto fm = painter->fontMetrics();
auto rect = fm.boundingRect(character);
painter->drawStaticText(-rect.width() / 2.0, -radius_outer + height * 1.0 / 4.0, QStaticText(character));
painter->restore();
};
drawer(angle_8_1 * 0.0, QString::fromStdU16String(sElementsTwo[0]));
drawer(angle_8_1 * 1.0, QString::fromStdU16String(sElementsTwo[1]));
drawer(angle_8_1 * 2.0, QString::fromStdU16String(sElementsTwo[2]));
drawer(angle_8_1 * 3.0, QString::fromStdU16String(sElementsTwo[3]));
drawer(angle_8_1 * 4.0, QString::fromStdU16String(sElementsTwo[4]));
drawer(angle_8_1 * 5.0, QString::fromStdU16String(sElementsTwo[5]));
drawer(angle_8_1 * 6.0, QString::fromStdU16String(sElementsTwo[6]));
drawer(angle_8_1 * 7.0, QString::fromStdU16String(sElementsTwo[7]));
}
void Qiankunmap::drawOneEighthSeperator(QPainter *painter, qreal radius1, qreal radius2)
{
static const auto PI = std::acos(-1);
static auto angle = 2 * PI / 8.0 / 2.0; // 弧度
static auto absSinAngle = std::abs(std::sin(angle));
static auto absCosAngle = std::abs(std::cos(angle));
auto a_1 = absSinAngle * radius1;
auto b_1 = absCosAngle * radius1;
auto a_2 = absSinAngle * radius2;
auto b_2 = absCosAngle * radius2;
QVector<QLineF> lines;
lines << QLineF(QPointF(-a_1, -b_1), QPointF(-a_2, -b_2))
<< QLineF(QPointF( a_1, -b_1), QPointF( a_2, -b_2))
<< QLineF(QPointF( b_1, -a_1), QPointF( b_2, -a_2))
<< QLineF(QPointF( b_1, a_1), QPointF( b_2, a_2))
<< QLineF(QPointF( a_1, b_1), QPointF( a_2, b_2))
<< QLineF(QPointF(-a_1, b_1), QPointF(-a_2, b_2))
<< QLineF(QPointF(-b_1, a_1), QPointF(-b_2, a_2))
<< QLineF(QPointF(-b_1, -a_1), QPointF(-b_2, -a_2));
painter->save();
painter->setPen(QPen(QBrush(QColor(0x2F4F4F)), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawLines(lines);
painter->restore();
}
void Qiankunmap::drawOneTwentyFourthSeperator(QPainter *painter, qreal radius1, qreal radius2)
{
static const auto PI = std::acos(-1);
static auto angle = 2 * PI / 24.0 / 2.0; // 弧度
static auto absSinAngle = std::abs(std::sin(angle));
static auto absCosAngle = std::abs(std::cos(angle));
auto a_1 = absSinAngle * radius1;
auto b_1 = absCosAngle * radius1;
auto a_2 = absSinAngle * radius2;
auto b_2 = absCosAngle * radius2;
QVector<QLineF> lines;
lines << QLineF(QPointF(-a_1, -b_1), QPointF(-a_2, -b_2))
<< QLineF(QPointF( a_1, -b_1), QPointF( a_2, -b_2))
<< QLineF(QPointF( b_1, -a_1), QPointF( b_2, -a_2))
<< QLineF(QPointF( b_1, a_1), QPointF( b_2, a_2))
<< QLineF(QPointF( a_1, b_1), QPointF( a_2, b_2))
<< QLineF(QPointF(-a_1, b_1), QPointF(-a_2, b_2))
<< QLineF(QPointF(-b_1, a_1), QPointF(-b_2, a_2))
<< QLineF(QPointF(-b_1, -a_1), QPointF(-b_2, -a_2));
painter->save();
painter->setPen(QPen(QBrush(QColor(Qt::black)), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawLines(lines);
painter->restore();
painter->save();
painter->rotate(angle_8_1);
painter->setPen(QPen(QBrush(QColor(Qt::black)), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawLines(lines);
painter->restore();
}
void Qiankunmap::drawQuarterSeperator(QPainter *painter, qreal radius1, qreal radius2)
{
static const auto PI = std::acos(-1);
static auto angle = 2 * PI / 4.0 / 2.0; // 弧度
static auto absSinAngle = std::abs(std::sin(angle));
static auto absCosAngle = std::abs(std::cos(angle));
auto a_1 = absSinAngle * radius1;
auto b_1 = absCosAngle * radius1;
auto a_2 = absSinAngle * radius2;
auto b_2 = absCosAngle * radius2;
QVector<QLineF> lines;
lines << QLineF(QPointF(-a_1, -b_1), QPointF(-a_2, -b_2))
<< QLineF(QPointF( a_1, -b_1), QPointF( a_2, -b_2))
<< QLineF(QPointF( a_1, b_1), QPointF( a_2, b_2))
<< QLineF(QPointF(-a_1, b_1), QPointF(-a_2, b_2));
painter->save();
painter->setPen(QPen(QBrush(QColor(Qt::red)), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawLines(lines);
painter->restore();
}
void Qiankunmap::onTimer()
{
degree_ += 15;
update();
}
主程序中调用代码如下:
#include "Qiankunmap.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Qiankunmap w;
w.show();
return a.exec();
}
至此八卦图基本元素完成,运行效果图如下
获取代码请前往:QT,C++实现的天干地支八卦图源代码-C++文档类资源-CSDN文库https://download.csdn.net/download/wastelandboy/81443268