当前位置: 首页 > article >正文

Qt:玩转QPainter后转之太极图(步骤详细、包含源码)

前言

简单了解了QPainter之后还是要做两个小例子练一练,不实际去做,只看看函数是没啥太大提升的,这里就简单画一个太极图。

正文

在这里插入图片描述

我们都知道太极分为阴阳鱼两部分,阴鱼(黑色)有个白色鱼眼,阳鱼(白色)有个黑色鱼眼;所以我们在画图的时候也可以分成阴阳两部分来画
单看阳鱼
在这里插入图片描述
不算鱼眼的话可以分成三部分,我们可以先画一个大半圆,用大半圆减去上面一个小半圆,再加上下面一个小半圆即可
阴鱼正好相反先画一个大半圆,用大半圆减去下面一个小半圆,再加上上面一个小半圆即可
关键代码

void BGPainter::drawTaiJi(QPainter& painter)
{
    // 先保存绘图设置
    painter.save();
    // 通过旋转坐标系统实现太极图的旋转
    painter.rotate(m_angle);

    // 白鱼
    QPainterPath circle, temp;
    // <<左移乘2
    circle.arcTo(-m_radius, -m_radius, m_radius << 1, m_radius << 1, 270, 180);
    // >>右移除2
    temp.addEllipse(QPointF(0, -m_radius >> 1), m_radius >> 1, m_radius >> 1);
    // 上面减一个小半圆
    circle -= temp;
    temp.clear();
    temp.addEllipse(QPointF(0, m_radius >> 1), m_radius >> 1, m_radius >> 1);
    // 下面加上一个小半圆
    circle += temp;
    painter.fillPath(circle, Qt::white);
    
    // 黑鱼
    circle.clear();
    circle.arcTo(-m_radius, -m_radius, m_radius << 1, m_radius << 1, 90, 180);
    temp.clear();
    temp.addEllipse(QPointF(0, m_radius >> 1), m_radius >> 1, m_radius >> 1);
    // 下面减一个小半圆
    circle -= temp;
    temp.clear();
    temp.addEllipse(QPointF(0, -m_radius >> 1), m_radius >> 1, m_radius >> 1);
    // 上面加上一个小半圆
    circle += temp;
    painter.fillPath(circle, Qt::black);

    painter.restore();
}

效果如下
在这里插入图片描述
现在再把鱼眼添加上,再加一个定时器来实现旋转即可
完整代码

#ifndef BGPAINTER_H
#define BGPAINTER_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class BGPainter; }
QT_END_NAMESPACE
enum Speed {
    VERYFAST = 5,
    FAST = 10,
    MEDIUM = 50,
    LOW = 100,
    LOWLOW = 200
};


class BGPainter : public QWidget
{
    Q_OBJECT

public:
 
    BGPainter(QWidget *parent = nullptr);
    void updateInterval(int speed);
    void initcboSpeed();
    ~BGPainter();
protected:
    void paintEvent(QPaintEvent* event) override;
    void drawTaiJi(QPainter& painter);

private slots:
    void on_btnBeignRotate_clicked();
    void on_btnEndRotate_clicked();

private:
    Ui::BGPainter *ui;
    // 太极图半径
    int m_radius;
    // 设置个定时器使得太极图旋转
    QTimer* m_timer;
    // 定时器的时间间隔
    int m_interval;
    // 旋转的角度
    int m_angle;
};
#endif // BGPAINTER_H

//cpp文件
#include "bgpainter.h"
#include <QPointF>
#include "qpainter.h"
#include "qpainterpath.h"
#include "qtimer.h"
#include "qpen.h"
#include "qbrush.h"
#include "ui_bgpainter.h"

BGPainter::BGPainter(QWidget* parent)
    : QWidget(parent)
    , ui(new Ui::BGPainter)
    , m_radius(100)
    , m_angle(0)
    , m_interval(200)
{
    ui->setupUi(this);
    m_timer = new QTimer(0);
    // 默认时间间隔为2ms
    m_timer->setInterval(m_interval);
    connect(m_timer, &QTimer::timeout, [=](){
        // 触发72次定时器才算完整一圈
        m_angle += 5;
        m_angle %= 360;
        update(); });
    initcboSpeed();
}

void BGPainter::updateInterval(int speed)
{
    m_interval = speed;
    m_timer->setInterval(m_interval);
}

void BGPainter::initcboSpeed()
{
    ui->cboSpeed->addItem("LOWLOW",static_cast<int>(Speed::LOWLOW));
    ui->cboSpeed->addItem("LOW",static_cast<int>(Speed::LOW));
    ui->cboSpeed->addItem("MEDIUM",static_cast<int>(Speed::MEDIUM));
    ui->cboSpeed->addItem("FAST",static_cast<int>(Speed::FAST));
    ui->cboSpeed->addItem("VERYFAST",static_cast<int>(Speed::VERYFAST));
    connect(ui->cboSpeed,QOverload<int>::of(&QComboBox::currentIndexChanged),this,[=](){
        int index = ui->cboSpeed->currentIndex();
        Speed speed = (Speed)ui->cboSpeed->itemData(index).toInt();
        updateInterval(speed);
    });
}

BGPainter::~BGPainter()
{
    delete ui;
    if (m_timer)
    {
        if (m_timer->isActive())
            m_timer->stop();

        delete m_timer;
        m_timer = nullptr;
    };
}

void BGPainter::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);
    // 图形和文本抗锯齿
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    // 将绘图起点移动到窗口中心
    painter.translate(width() / 2, height() / 2);
    // 画太极
    drawTaiJi(painter);

}

void BGPainter::drawTaiJi(QPainter& painter)
{
    // 先保存绘图设置
    painter.save();
    // 通过旋转坐标系统实现太极图的旋转
    painter.rotate(m_angle);

    // 白鱼
    QPainterPath circle, temp;
    // <<左移乘2
    circle.arcTo(-m_radius, -m_radius, m_radius << 1, m_radius << 1, 270, 180);
    // >>右移除2
    temp.addEllipse(QPointF(0, -m_radius >> 1), m_radius >> 1, m_radius >> 1);
    // 上面减一个小半圆
    circle -= temp;
    temp.clear();
    temp.addEllipse(QPointF(0, m_radius >> 1), m_radius >> 1, m_radius >> 1);
    // 下面加上一个小半圆
    circle += temp;
    painter.fillPath(circle, Qt::white);
    // 黑鱼眼
    temp.clear();
    temp.addEllipse(QPointF(0, m_radius >> 1), m_radius >> 3, m_radius >> 3);
    painter.fillPath(temp, Qt::black);
    // 黑鱼
    circle.clear();
    circle.arcTo(-m_radius, -m_radius, m_radius << 1, m_radius << 1, 90, 180);
    temp.clear();
    temp.addEllipse(QPointF(0, m_radius >> 1), m_radius >> 1, m_radius >> 1);
    // 下面减一个小半圆
    circle -= temp;
    temp.clear();
    temp.addEllipse(QPointF(0, -m_radius >> 1), m_radius >> 1, m_radius >> 1);
    // 上面加上一个小半圆
    circle += temp;
    painter.fillPath(circle, Qt::black);
    // 白鱼眼
    temp.clear();
    temp.addEllipse(QPointF(0, -m_radius >> 1), m_radius >> 3, m_radius >> 3);
    painter.fillPath(temp, Qt::white);

    painter.restore();
}

void BGPainter::on_btnBeignRotate_clicked()
{
    m_timer->start();
}

void BGPainter::on_btnEndRotate_clicked()
{
    if (m_timer->isActive()) {
        m_timer->stop();
    }
}

最后效果

taijiYanshi


http://www.kler.cn/a/292454.html

相关文章:

  • 软件开发专用术语介绍
  • HTML元素拓展:data-*属性的应用与实践
  • 国产芯片LT6911UXE/C:HDMI 2.0转MIPI DSI/CSI转换器,4K超清
  • 【数据结构-二维前缀和】【列维护优化】力扣3212. 统计 X 和 Y 频数相等的子矩阵数量
  • EmguCV学习笔记 VB.Net 9.2 VideoWriter类
  • 谷歌seo网址如何快速被收录?
  • 大模型笔记01--基于ollama和open-webui快速部署chatgpt
  • 13.5 Files类操作梳理(下)
  • docker 启动ElasticSearch
  • uniapp组件知识记录
  • 数据赋能(192)——开发:数据服务——影响因素、直接作用、主要特征
  • 详解 MQ 消息队列
  • el-table使用#header自定义表头后脱离响应式问题处理
  • docker国内镜像源报错解决方案
  • docker 介绍以及常用命令
  • Meta关闭Spark AR平台:未来规划与影响分析
  • 2-81 基于matlab的SAR图像的相干斑抑制
  • 【微信小程序】自定义 tabBar
  • 服务器禁用远程(22)
  • flutter Timer报错