基于C++,QT开发的天干地支罗盘实现思路

山前大桥下,有一个傻瓜。一枚小学生,幽居荒山中。养了一群狗,还有一只猫。喜欢搞编程,缺钱打零工。数理史皆通,法文记心中。下厨会做饭,挥毫能舞文。

注意:文中代码与下面图像不是同一套代码,下面的图片为最终的运行效果图,由于代码非常长,而受限于篇幅限制示例中的代码为开发之初测试代码,原理相同。用于学习目的

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

有关更多技术分享与交流请加QQ群:717743458。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值