Windows图形界面(GUI)-QT-C/C++ - Qt图形绘制详解

news2025/1/15 21:31:24
  • 公开视频 -> 链接点击跳转公开课程
  • 博客首页 -> ​​​链接点击跳转博客主页

目录

Qt绘图基础

QPainter概述

基本工作流程

绘图事件系统

paintEvent事件

重绘机制

文字绘制技术

基本文字绘制

​编辑

高级文字效果

基本图形绘制

线条绘制

​编辑

形状绘制

​编辑

图片处理

基本图片绘制

高级图片效果

​编辑

特效与动画

渐变效果

​编辑

时钟绘制


Qt绘图基础

QPainter概述

QPainter是Qt中的核心绘图类,提供了高度抽象的2D绘图功能。它允许我们在各种设备上进行绘制,包括:

  • 窗口部件(QWidget)
  • 像素图(QPixmap)
  • 图像(QImage)

基本工作流程

void Widget::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);  

    // 设置绘图属性
    painter.setRenderHint(QPainter::Antialiasing); 

    // 进行绘制操作
    painter.drawLine(0, 0, 100, 100);
}

 

绘图事件系统

paintEvent事件

paintEvent是Qt中处理绘制的核心事件,在以下情况会被触发:

  • 窗口首次显示
  • 窗口从最小化恢复
  • 窗口被其他窗口遮挡后重新显示
  • 调用update()或repaint()函数

重绘机制

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void paintEvent(QPaintEvent* event) override
    {
        QPainter painter(this);
        // 绘制代码
    }

    void updateContent()
    {
        update();  // 请求重绘,异步
        // repaint();  // 立即重绘,同步
    }

private:
    Ui::Widget *ui;
};

文字绘制技术

基本文字绘制

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void paintEvent(QPaintEvent*) override
    {
        QPainter painter(this);

        // 设置字体
        QFont font("Arial", 20);
        font.setBold(true);
        painter.setFont(font);

        // 设置颜色
        painter.setPen(QColor(255, 0, 0));

        // 绘制文本
        painter.drawText(rect(), Qt::AlignCenter, "Hello Qt!");
    }

private:
    Ui::Widget *ui;
};

高级文字效果

    void paintEvent(QPaintEvent*) override
    {
        QPainter painter(this);

        // 文字阴影效果
        QFont font("Times", 40);
        painter.setFont(font);

        // 绘制阴影
        painter.setPen(QColor(0, 0, 0, 127));
        painter.drawText(rect().adjusted(2, 2, 2, 2),
                         Qt::AlignCenter, "Shadow Text");

        // 绘制主文本
        painter.setPen(Qt::white);
        painter.drawText(rect(), Qt::AlignCenter, "Shadow Text");
    }

基本图形绘制

线条绘制

void paintEvent(QPaintEvent*) override  
{  
    QPainter painter(this);  
    
    // 设置画笔  
    QPen pen(Qt::red, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);  
    painter.setPen(pen);  
    
    // 绘制各种线条  
    painter.drawLine(10, 10, 100, 100);  // 直线  
    painter.drawArc(10, 120, 80, 80, 0, 180 * 16);  // 圆弧  
}

形状绘制

   void paintEvent(QPaintEvent*) override  
    {  
        QPainter painter(this);  
        
        // 矩形  
        painter.fillRect(10, 10, 90, 60, Qt::blue);  
        
        // 圆形  
        painter.drawEllipse(120, 10, 90, 90);  
        
        // 多边形  
        QPolygon polygon;  
        polygon << QPoint(10,100) << QPoint(110,100)   
                << QPoint(60,180);  
        painter.drawPolygon(polygon);  
    }

图片处理

基本图片绘制

void paintEvent(QPaintEvent*) override  
{  
    QPainter painter(this);  
    
    QPixmap pixmap(":/images/example.png");  
    painter.drawPixmap(10, 10, pixmap);  
}

高级图片效果

    void paintEvent(QPaintEvent*) override
    {
        QPainter painter(this);

        QPixmap pixmap("C:\\Users\\Administrator\\Desktop\\图形界面-QT.png");

        // 图片缩放
        QPixmap scaled = pixmap.scaled(200, 200,
                                       Qt::KeepAspectRatio,
                                       Qt::SmoothTransformation);

        // 添加圆形裁剪
        QPainterPath path;
        path.addEllipse(10, 10, 200, 200);
        painter.setClipPath(path);
        painter.drawPixmap(10, 10, scaled);
    }

特效与动画

渐变效果

void paintEvent(QPaintEvent*) override  
{  
    QPainter painter(this);  
    
    // 线性渐变  
    QLinearGradient gradient(0, 0, width(), height());  
    gradient.setColorAt(0, Qt::red);  
    gradient.setColorAt(1, Qt::blue);  
    
    painter.fillRect(rect(), gradient);  
}

时钟绘制

class ClockWidget : public QWidget
{
    Q_OBJECT

public:
    explicit ClockWidget(QWidget *parent = nullptr) : QWidget(parent)
    {

        setFixedSize(400, 400);

        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, QOverload<>::of(&ClockWidget::update));
        timer->start(1000);
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event);

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);

        painter.translate(width() / 2, height() / 2);

        QTime currentTime = QTime::currentTime();

        drawClockPlate(&painter);

        drawHourHand(&painter, currentTime);

        drawMinuteHand(&painter, currentTime);

        drawSecondHand(&painter, currentTime);

        drawCenterPoint(&painter);
    }

private:
    void drawClockPlate(QPainter *painter)
    {

        QPen pen(Qt::black);
        pen.setWidth(2);
        painter->setPen(pen);

        painter->setBrush(Qt::white);

        painter->drawEllipse(-180, -180, 360, 360);

        for (int i = 0; i < 60; ++i) {

            painter->save();

            painter->rotate(6.0 * i);

            if (i % 5 == 0) {

                pen.setWidth(3);
                painter->setPen(pen);
                painter->drawLine(0, -160, 0, -145);

                painter->save();
                painter->rotate(-6.0 * i);
                QFont font("Arial", 15, QFont::Bold);
                painter->setFont(font);

                int num = (i / 5 == 0) ? 12 : i / 5;

                QRect textRect(-20, -190, 40, 40);
                painter->drawText(textRect, Qt::AlignCenter, QString::number(num));
                painter->restore();
            } else {

                pen.setWidth(1);
                painter->setPen(pen);
                painter->drawLine(0, -160, 0, -150);
            }

            painter->restore();
        }
    }

    void drawHourHand(QPainter *painter, const QTime &time)
    {
        painter->save();

        double angle = 30.0 * (time.hour() % 12) + 0.5 * time.minute();
        painter->rotate(angle);

        QPen pen(Qt::black, 4);
        painter->setPen(pen);

        painter->drawLine(0, 0, 0, -80);

        painter->restore();
    }

    void drawMinuteHand(QPainter *painter, const QTime &time)
    {
        painter->save();

        double angle = 6.0 * time.minute() + 0.1 * time.second();
        painter->rotate(angle);

        QPen pen(Qt::blue, 3);
        painter->setPen(pen);

        painter->drawLine(0, 0, 0, -120);

        painter->restore();
    }

    void drawSecondHand(QPainter *painter, const QTime &time)
    {
        painter->save();

        double angle = 6.0 * time.second();
        painter->rotate(angle);

        QPen pen(Qt::red, 2);
        painter->setPen(pen);

        painter->drawLine(0, 20, 0, -140);

        painter->restore();
    }

    void drawCenterPoint(QPainter *painter)
    {
        painter->setPen(Qt::NoPen);
        painter->setBrush(Qt::red);
        painter->drawEllipse(-8, -8, 16, 16);

        painter->setBrush(Qt::black);
        painter->drawEllipse(-4, -4, 8, 8);
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2277188.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenArk64:Windows 系统分析与逆向工程工具详解

引言 在 Windows 系统的底层操作和逆向工程领域&#xff0c;OpenArk 是一款备受推崇的开源工具集。而 OpenArk64.exe 是 OpenArk 工具的 64 位版本&#xff0c;专门用于 64 位 Windows 系统。它提供了强大的功能&#xff0c;帮助用户深入分析系统内核、进程、文件、注册表等&a…

浅谈计算机网络02 | SDN控制平面

计算机网络控制平面 一、现代计算机网络控制平面概述1.1 与数据平面、管理平面的关系1.2 控制平面的发展历程 二、控制平面的关键技术剖析2.1 网络层协议2.1.1 OSPF协议2.1.2 BGP协议 2.2 SDN控制平面技术2.2.1 SDN架构与原理2.2.2 OpenFlow协议2.2.3 SDN控制器 一、现代计算机…

【C++】PP5015 [NOIP2018 普及组] 标题统计

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示数据规模与约定 &#x1f4af;方法分析方法1&#xff1a;我的做法实…

从玩具到工业控制--51单片机的跨界传奇【2】

咱们在上一篇博客里面讲解了什么是单片机《单片机入门》&#xff0c;让大家对单片机有了初步的了解。我们今天继续讲解一些有关单片机的知识&#xff0c;顺便也讲解一下我们单片机用到的C语言知识。如果你对C语言还不太了解的话&#xff0c;可以看看博主的C语言专栏哟&#xff…

线程池面试题目集合

最近面试中总是问到ThreadPoolExecutor类相关问题&#xff0c;在此集中整理下。 问题1.ThreadPoolExecutor的关键参数是哪些&#xff0c;任务添加过程中&#xff0c;内部线程是怎样构建的&#xff1f; a)任务到达时&#xff0c;线程池数目小于核心线程数corePoolSize&#xff0…

程序员独立开发竞品分析:确定网站使用什么建站系统

要确定一个网站使用的建站系统&#xff0c;可以通过以下几种方法尝试分析&#xff1a; 查看页面源代码&#xff1a; 打开网站&#xff0c;右键点击页面并选择“查看页面源代码”。在代码中查找一些常见的建站系统标志&#xff0c;例如&#xff1a; WordPress 的迹象&#xff1a…

基于Media+Unity的手部位姿三维位姿估计

使用mediapipe Unity 手部位姿三维位姿估计 参考文章 基于Mediapipe的姿势识别并同步到Unity人体模型中 MediapipeUnity3d实现虚拟手_unity mediapipe-CSDN博客 需求 我的需求就是快速、准确的跟踪手部位姿并实现一个三维显示。 主要思路 搭建mdeiapipe系统&#xff0c…

构建高性能网络服务:从 Socket 原理到 Netty 应用实践

1. 引言 在 Java 网络编程中&#xff0c;Socket 是实现网络通信的基础&#xff08;可以查看我的上一篇博客&#xff09;。它封装了 TCP/IP 协议栈&#xff0c;提供了底层通信的核心能力。而 Netty 是在 Socket 和 NIO 的基础上&#xff0c;进一步封装的高性能、异步事件驱动的…

Python入门10:高阶函数

一、什么是高阶函数 1.1、高阶函数的概念和作用&#xff1a; 高阶函数是指 接受函数作为参数 或者 返回函数 作为结果的函数。它在函数式编程中是一个重要概念&#xff08;函数式编程&#xff08;Functional Programming &#xff0c; FP &#xff09;是一 种编程范式&#xf…

python-leetcode-矩阵置零

73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09; class Solution:def setZeroes(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""m, n len(matrix), len(matrix[0])row_zero …

MySQL数据库(SQL分类)

SQL分类 分类全称解释DDLData Definition Language数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库&#xff0c;表&#xff0c;字段&#xff09;DMLData Manipulation Language数据操作语言&#xff0c;用来对数据库表中的数据进行增删改DQLData Query Languag…

计算机网络 笔记 网络层1

网络层功能概述 主要的任务是把分组从源端传输到目的端&#xff0c;为分组交换网上的不同主句提供通信服务&#xff0c;网络层的传输单位是数据报。 主要的功能&#xff1b; 1&#xff0c;路由选择&#xff1a;路由选择指网络层根据特定算法&#xff0c;为数据包从源节点到目…

MyBatis-什么是MyBatis?以及MyBatis的快速入门。

简介 什么是 MyBatis&#xff1f; 什么是MyBatis? MyBatis是一款优秀的 持久层 框架&#xff0c;用于简化JDBC的开发。&#xff08;框架&#xff1a;是一个半成品软件&#xff0c;是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、…

Linux Kernel 之十 详解 PREEMPT_RT、Xenomai 的架构、源码、构建及使用

概述 现在的 RTOS 基本可以分为 Linux 阵营和非 Linux 阵营这两大阵营。非 Linux 阵营的各大 RTOS 都是独立发展,使用上也相对独立;而 Linux 阵营则有多种不同的实现方法来改造 Linux 以实现实时性要求。本文我们重点关注 Linux 阵营的实时内核实现方法! 本文我们重点关注 …

Swift 趣味开发:查找拼音首字母全部相同的 4 字成语(上)

概述 Swift 语言是一门现代化、安全、强大且还算性感的语言。在去年 WWDC 24 中苹果正式推出了秃头码农们期待许久的 Swift 6.0&#xff0c;它进一步完善了 Swift 语言的语法和语义&#xff0c;并再接再厉——强化了现代化并发模型的安全性和灵活性。 这里我们不妨用 Swift 来…

docker一张图理解

1、push 将本地的镜像上传到镜像仓库,要先登陆到镜像仓库。参数说明&#xff1a; –disable-content-trust : 忽略镜像的校验,默认开启 # 上传本地镜像myapache:v1到镜像仓库中。 docker push myapache:v1 1.2、search 从Docker Hub查找镜像。参数说明&#xff1a; –…

IoTDB 常见问题 QA 第三期

关于 IoTDB 的 Q & A IoTDB Q&A 第三期持续更新&#xff01;我们将定期汇总我们将定期汇总社区讨论频繁的问题&#xff0c;并展开进行详细回答&#xff0c;通过积累常见问题“小百科”&#xff0c;方便大家使用 IoTDB。 Q1&#xff1a;查询最新值 & null 数据相加方…

MyBatis实现数据库的CRUD

本文主要讲解使用MyBatis框架快速实现数据库中最常用的操作——CRUD。本文讲解的SQL语句都是MyBatis基于注解的方式定义的&#xff0c;相对简单。 Mybatis中#占位符和$拼接符的区别 “#”占位符 在使用MyBatis操作数据库的时候&#xff0c;可以直接使用如下SQL语句删除一条数…

Spring Boot 下的Swagger 3.0 与 Swagger 2.0 的详细对比

先说结论&#xff1a; Swgger 3.0 与Swagger 2.0 区别很大&#xff0c;Swagger3.0用了最新的注释实现更强大的功能&#xff0c;同时使得代码更优雅。 就个人而言&#xff0c;如果新项目推荐使用Swgger 3.0&#xff0c;对于工具而言新的一定比旧的好&#xff1b;对接于旧项目原…

关于2025年智能化招聘管理系统平台发展趋势

2025年&#xff0c;招聘管理领域正站在变革的十字路口&#xff0c;全新的技术浪潮与不断变化的职场生态相互碰撞&#xff0c;促使招聘管理系统成为重塑企业人才战略的关键力量。智能化招聘管理系统平台在这一背景下迅速崛起&#xff0c;其发展趋势不仅影响企业的招聘效率与质量…