【嵌入式Qt开发入门】如何使用Qt进行绘图——QPainter 绘图

news2024/11/27 4:24:04

        绘图与图表在嵌入式里有的比较多,尤其是图表,我们常在股票里看到的“图表折线/曲线 图/饼状图等”都可以用 Qt 的图表来实现。绘图和图表的内容本章主要介绍绘图和图表的基本操作,以简单的例子呈现绘图与图表的用法,目的就是快速入门绘图与图表,关于绘图与图表详解最好是看 Qt 官方的帮助文档。

QPainter 绘图

        Qt 里的所有绘图,比如一个按钮和一个 Label 的显示,都有绘图系统来执行。绘图系统基于 QPainter、QPaintDevice 和 QPainEngine 类。QPainter 是可以直接用来操作绘图的类,而 QPaintDevice 和 QPainEngine 都比 QPainter 更底层,我们只需要了解一下 QPaintDevice 和 QPainEngine 就行了。可以用下面一张图来表示它们的关系。

        一般用于显示的类,如 QWidget、QPixmap、QImage、Qlabel 等可视类控件都可以充当绘 图区域的“画布”,从 QWidget 继承的类都有 virtual void paintEvent(QPaintEvent *event);属性。这个 paintEvent()是一个虚函数,它在 qwidget.h 头文件的 protected:修饰符下。

        paintEvent()事件可以被重写。(解释:什么是绘图事件?可以这么理解,当界面初始化或者需要刷新时才会执行的事件,也就是说绘图事件在构造对象实例化时会执行,需要刷新界面我们可以使用 update()方法执行 paintEvent()事件)。

        paintEvent()事件是父类 QWidget 提供给子类的接口,在父类里定义为空,所以可以说 paintEvent()事件就是专门给子类画图用的。

        paintEvent()事件在子类重写的基本结构如下:

void Widget::paintEvent(QPaintEvent *)
{
    /* 指定画图的对象,this 代表是本 Widget */
    QPainter painter(this);
    // 使用 painter 在对象上绘图...
}

应用实例

        本例目的:快速了解 paintEvent()事件的使用。

        项目名称:qpainter。本例使用一张 CD 图片,用 QPainter 在 paintEvent()将 CD 画在窗口的中心,并且每 100ms 旋转 1 度角度。所以 CD 看起来是旋转了的效果。

        头文件“mainwindow.h”具体代码如下。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
#include <QTimer>

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    /* 重写父类下的protected方法*/
protected:
    void paintEvent(QPaintEvent *);

private:
    /* 定时器,用于定时更新界面 */
    QTimer *timer;
    /* 角度 */
    int angle;

private slots:
    /* 槽函数 */
    void timerTimeOut();

};
#endif // MAINWINDOW_H

        因为 paintEvent()是父类 QWidget 的 protected 修饰符下虚方法(虚函数),所以建议重写时也写到子类下的 protected 修饰符下。

        在源文件“mainwindow.cpp”具体代码如下。

#include "mainwindow.h"
#include "QDebug"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    /* 设置主窗口位置及颜色 */
    this->setGeometry(0, 0, 800, 480);
    setPalette(QPalette(Qt::gray));
    setAutoFillBackground(true);

    /* 定时器实例化 */
    timer = new QTimer(this);

    /* 默认角度为0 */
    angle = 0;

    /* 定时100ms */
    timer->start(100);

    /* 信号槽连接 */
    connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeOut()));
}

MainWindow::~MainWindow()
{
}

void MainWindow::timerTimeOut()
{
    /* 需要更新界面,不设置不更新 */
    this->update();
}

void MainWindow::paintEvent(QPaintEvent *)
{
    /* 指定父对象,this指本窗口 */
    QPainter painter(this);

    /* 设置抗锯齿,流畅转换 */
    painter.setRenderHints(QPainter::Antialiasing
                           | QPainter::SmoothPixmapTransform);
    /* 计算旋转角度 */
    if (angle++ == 360)
        angle = 0;

    /* QPixmap类型对象 */
    QPixmap image;

    /* 加载 */
    image.load(":/image/cd.png");

    /* QRectF即,继承QRect(Qt的矩形类),F代表精确到浮点类型 */
    QRectF rect((this->width() - image.width()) / 2,
                (this->height() - image.height()) / 2,
                image.width(),
                image.height());

    /* 默认参考点为左上角原点(0,0),因为旋转需要以图形的中心为参考点,
     * 我们使用translate把参考点设置为CD图形的中心点坐标 */
    painter.translate(0 + rect.x() + rect.width() / 2,
                      0 + rect.y() + rect.height() / 2);

    /* 旋转角度 */
    painter.rotate(angle);

    /* 现在参考点为CD图形的中心,我们需要把它设置回原点的位置,
     * 所以需要减去上面加上的数 */
    painter.translate(0 - (rect.x() + rect.width() / 2),
                      0 - (rect.y() + rect.height() / 2));

    /* 画图,QPainter提供了许多drawX的方法 */
    painter.drawImage(rect, image.toImage(), image.rect());

    /* 再画一个矩形 */
    painter.drawRect(rect.toRect());
}

        首先实现paintEvent()。先指定需要画图的对象,加图片后,使用 translate() 设置参考原点,旋转一定的角度后再恢复参考原点。之后就开始画图。在参考原点处可能比较难理解,大家根据上面的注释多多分析。

        然后,定时100ms 更新一次界面。因为 paintEvent事件在构造函数执行时只会执行一次。 我们需要使用 update()方法来更新界面,才能看到 CD 旋转的效果。

程序运行效果

        编译运行程序后可以看到如下效果,CD 的外框加画了一个矩形,使旋转更明显。使用 paintEvent 可以实现一些需要绘图的情景,它可能比 Qt 动画类更容易实现。结合 Qt 的画笔, 也可以设计一个绘图软件,这多得益于 paintEvent()与 QPainter 使界面开发多了一些可能。在界面设计里,重绘界面使用 paintEvent()也比较多,需要我们掌握这部分内容。

 

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

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

相关文章

抖音怎么私信发名片

抖音怎么私信发名片&#xff0c;抖音私信卡片制作教程来了&#xff0c;视频版教程#新媒体运营工具#软件#抖音消息卡片 hello&#xff0c;大家&#xff0c;我是百收网SEO&#xff0c;今天给大家说一下个人号自动回复卡片&#xff0c;相比企业号自动回复卡片&#xff0c;它的优势…

MATLAB | 终于找到了修改图例图标的方法(可以自己设计图例啦?)

讲一点扒MATLAB底裤的事情叭&#xff0c;就是之前写的有一些绘图函数&#xff0c;比如阴影柱状图&#xff0c;想要把图例里的图标进行修改让其也带着阴影&#xff0c;我采取的是直接绘制一些会检测图例框移动的阴影图标来冒充图例的图标&#xff0c;那么有没有办法真正的自定义…

如何轻松应对广泛存在开源“0Day”

跟不少安全人员讨论过一个很通俗的话题 作为网安从业者最讨厌的是什么&#xff1f; 不同的人给了很多不同的答案 有的人说&#xff1a; 但更多的人都在说&#xff1a; “零日漏洞”(zero-day)又叫零时差攻击&#xff0c;是指被发现后立即被恶意利用的安全漏洞。通俗地讲&…

QScintilla自制代码编辑器系列(1)编译库文件与运行测试例子

1.下载工程源码 我本人机器上的QT是6.4 可以下载最新的代码 https://www.riverbankcomputing.com/static/Downloads/QScintilla/2.14.0/QScintilla_src-2.14.0.zip 2. 编译生成文件 无需改动可以顺利生成库文件 3. 运行例子 1&#xff09;拷贝头文件 将整个Qsci文件夹拷…

面试官:你的项目有什么亮点?我:解决了JS脚本加载失败的问题!

前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 面试官&#xff1a;你的项目有什么亮点&#xff1f;解决了什么问题&#xff1f; 你&#xff1a;嗯...... 面试官&#…

7.3 【Linux】磁盘的分区、格式化、检验与挂载

想在系统中新增一颗磁盘时&#xff0c;需要做&#xff1a; 1.对磁盘进行分区&#xff0c;以创建可用的partition&#xff1b; 2.对该partition进行格式化&#xff08;format),以创建系统可用的filesystem&#xff1b; 3.可对刚刚创建好的filesystem进行检验&#xff1b; 4.…

Acrel-5000重点用能单位能耗在线监测系统在湖南三立集团的案例分析

安科瑞 崔丽洁 摘要&#xff1a;根据《重点用能节能办法》&#xff08;国家发展改革委等第七部委2018年15号令&#xff09;、《重点用能单位能耗在线监测系统推广建设工作方案》&#xff08;发改环资[2017]1711号&#xff09;和《关于加速推进重点用能单位能耗在线监测系统建设…

介绍几种OPTIONS检测的方法

概述 日常的VOIP开发中&#xff0c;OPTIONS检测是常用的网络状态检测工具。 OPTIONS原本是作为获取对方能力的消息&#xff0c;也可以检测当前服务状态。正常情况下&#xff0c;UAS收到OPTIONS心跳&#xff0c;直接回复200即可。 与ping不同的是&#xff0c;OPTIONS检测不仅…

前后端分离开发

目录 前后合开发&#xff08;不推荐&#xff09; 前后端分离开发&#xff08;主流&#xff09; 项目开发的基本步骤 接口文档的管理平台--YApi 前后合开发&#xff08;不推荐&#xff09; 沟通成本高分工不明确不便于管理不便于扩展 前后端分离开发&#xff08;主流&…

让浮动元素在一行显示

&#x1f4dd;个人主页&#xff1a;爱吃炫迈 &#x1f48c;系列专栏&#xff1a;HTMLCSS &#x1f9d1;‍&#x1f4bb;座右铭&#xff1a;道阻且长&#xff0c;行则将至&#x1f497; <div class"wrap"><div class"item">1</div><di…

ubuntu实现自动挂载u盘

ubuntu实现自动挂载u盘 但是&#xff0c;有些设施可以在没有图形工具的情况下进行复制&#xff0c;并且在系统上占用的空间非常小。 例如&#xff0c;在我的设置中&#xff0c;我已经实现了USB自动挂载服务&#xff0c;而无需使用任何外部工具/服务&#xff0c;只有udev和syst…

Junit5相关技术

Selenium自动化测试框架 Junit针对Java的单元测试框架 拿一个技术写自动化测试用例&#xff08;Selenium3&#xff09; 拿一个技术管理已经编写好的测试用例(Junit5) 写代码前需要添加依赖&#xff1a;Junit5 一、注解 1.1 Test 表示当前这个方法是一个测试用例 1.2 Di…

DCN v2阅读笔记

Deformable ConvNets v2: More Deformable, Better Results 是 Deformable Convolutional Networks 研究的续作&#xff0c;发表在 CVPR 2019上。 作者对 DCNv1 的自适应行为进行研究&#xff0c;观察到虽然其神经特征的空间支持比常规的卷积神经网络更符合物体结构&#xff0…

2023年的无线蓝牙耳机哪些牌子好,真无线蓝牙耳机品牌排名

本文将为您详细介绍每款蓝牙耳机的设计特点、音质表现、续航能力和智能功能等关键信息。我们将提供客观、全面的分析&#xff0c;帮助您更好地了解每款产品的优势和适用场景&#xff1b;无论您是追求高保真音质的音乐发烧友&#xff0c;还是需要轻便舒适的耳机进行运动&#xf…

Kafka入门, 消费者工作流程(十八)

kafka消费方式 pull(拉)模式&#xff1a; consumer采用从broker中主动拉取数据。 Kafka采用这种方式。 push(推)模式&#xff1a; Kafka没有采用这种方式&#xff0c;因为由broker决定消息发送速率&#xff0c;很难适应所有消费者的速率。例如推送速度是50m/s&#xff0c;consu…

rocketmq客户端日志过大造成磁盘使用率占用过高

目录 问题现象 排查占用 自定义客户端日志配置未生效 总结 问题现象 收到项目报警&#xff1a;磁盘占用率超标通知 排查占用 从上述可以看出&#xff0c;实质是跟正常业务日志无关的&#xff0c;/home/work/log挂出来了&#xff0c;与/根目录下无关 查看根目录下日志占用…

frp实现远程开机

前一篇刷完小米路由器后&#xff0c;自带了frp&#xff0c;所以继续走着 前提&#xff1a;(我有阿里云公网服务器、域名&#xff09; 第一步&#xff0c;配置路由器&#xff08;客户端&#xff09;frp [common] server_addr frp.xxx.cn #需要在阿里云服务器添加解析 serve…

【macOS 系列】如何取消程序坞下方app的未读消息的小红点

如何取消程序坞下方app的未读消息的小红点 需要针对单独的软件一次设置&#xff0c;不能批量设置。将标记为APP图标取消勾选即可。

【UnityDOTS 七】IAspect的使用

IAspect的使用 前言 IAspect是Unity DOTS中用来更方便组织数据集合的接口。可以将我们需要的数据集合放到一个IAspect中&#xff0c;然后用这个自定义的IAspect去进行查询。 一、IAspect是什么&#xff1f; 如上面官方文档说的&#xff0c;是一个高级的Component组合体。 可以…

Gartner发布2023新兴技术雷达图,超级自动化安全、生成式AI是高影响力技术

在Gartner发布的“2023新兴技术影响力雷达图”中&#xff0c;围绕智能世界、生产力革命、透明度和隐私****以及关键使能技术四大主题&#xff0c;对24种最具颠覆和市场变革性的新兴趋势和技术进行了评估。 其中&#xff0c;边缘AI、边缘计算机视觉处于雷达图核心位置&#xff…