QT:图像上绘制图形
需求描述
1、展示一张图像
2、在图像上可以使用数据绘制图像:矩形、不规则图形、线条
3、有按键可以选择
概要设计
规划布局如下
1、左边是Qlabel 用于展示图片
2、右边是三个按钮

具体实现
1、 首先设计 UI 界面,对控件进行布局
在 mainwindow.ui 文件里,运用 Qt Designer 进行如下操作:
拖入一个 QWidget 到主窗口,这个 QWidget 将作为绘图区域。
拖入四个 QPushButton 到主窗口,把它们的 text 属性分别设置为“选择图片” “绘制矩形”、“绘制不规则图形” 和 “绘制线”。
pushButton_img
pushButton_Rectangle
pushButton_IrregularShape
pushButton_Line

2、新建类DrawingWidget
// DrawingWidget.cpp
#include "DrawingWidget.h"
#include <QPainter>DrawingWidget::DrawingWidget(QWidget *parent) : QWidget(parent)
{QPalette palette = this->palette();palette.setColor(QPalette::Window, Qt::black);this->setAutoFillBackground(true);this->setPalette(palette);
}DrawingWidget::~DrawingWidget()
{
}
// DrawingWidget.h
#ifndef DRAWINGWIDGET_H
#define DRAWINGWIDGET_H#include <QWidget>class DrawingWidget : public QWidget
{Q_OBJECT
public:explicit DrawingWidget(QWidget *parent = nullptr);~DrawingWidget();};#endif // DRAWINGWIDGET_H
3、将现有控件提升
在 Qt Designer 中,右键单击刚刚拖入的 QWidget,选择 “提升为”。
在 “提升的类名称” 中输入 DrawingWidget。
在 “头文件” 中输入 DrawingWidget.h。
点击 “添加”,再点击 “提升”。此时,该 QWidget 就被提升为 DrawingWidget 类的实例。

点击运行

4、添加按键信号槽函数
在mainwindow.h当中添加:
private slots:void on_pushButton_img_clicked(); // 声明槽函数void on_pushButton_Rectangle_clicked(); // 声明槽函数void on_pushButton_IrregularShape_clicked(); // 声明槽函数void on_pushButton_Line_clicked(); // 声明槽函数
在mainwindow.cpp当中添加:
void MainWindow::on_pushButton_img_clicked()
{QString buttonText = ui->pushButton_img->text();qDebug() << "点击的按钮内容是: " << buttonText;
}void MainWindow::on_pushButton_Rectangle_clicked()
{QString buttonText = ui->pushButton_Rectangle->text();qDebug() << "点击的按钮内容是: " << buttonText;
}void MainWindow::on_pushButton_IrregularShape_clicked()
{QString buttonText = ui->pushButton_IrregularShape->text();qDebug() << "点击的按钮内容是: " << buttonText;}void MainWindow::on_pushButton_Line_clicked()
{QString buttonText = ui->pushButton_Line->text();qDebug() << "点击的按钮内容是: " << buttonText;}
在 Qt 中,void on_pushButton_clicked(); 这种形式的槽函数是一种特殊的命名规则,它遵循了 Qt 的自动信号 - 槽连接机制。这种机制允许你通过特定的命名约定让 Qt 自动将信号和槽连接起来,而无需手动调用 connect 函数。
自动连接机制规则
当你使用这种以 on_ 开头,接着是控件对象名(例如 pushButton),再接着是信号名(例如 clicked),最后以 () 结尾的命名方式定义槽函数时,Qt 会在调用 ui->setupUi(this); 时自动进行信号 - 槽的连接。
5、图片选择
在DrawingWidget.h 当中添加loadImage函数声明
// DrawingWidget.h
#ifndef DRAWINGWIDGET_H
#define DRAWINGWIDGET_H#include <QWidget>
#include <QImage>class DrawingWidget : public QWidget
{Q_OBJECT
public:explicit DrawingWidget(QWidget *parent = nullptr);~DrawingWidget();void loadImage(const QString &fileName);void paintEvent(QPaintEvent *event) override;private:QImage m_image;
};#endif // DRAWINGWIDGET_H
在DrawingWidget.cpp 当中添加函数细节
// DrawingWidget.cpp
#include "DrawingWidget.h"
#include <QPainter>DrawingWidget::DrawingWidget(QWidget *parent) : QWidget(parent)
{QPalette palette = this->palette();palette.setColor(QPalette::Window, Qt::black);this->setAutoFillBackground(true);this->setPalette(palette);
}DrawingWidget::~DrawingWidget()
{
}void DrawingWidget::loadImage(const QString &fileName)
{if (m_image.load(fileName)) {qDebug() << "图片加载成功: " << fileName;update();} else {qDebug() << "图片加载失败: " << fileName;}}void DrawingWidget::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);QPainter painter(this);if (!m_image.isNull()) {painter.drawImage(0, 0, m_image);}}
“选择图片”按键,对应的函数
void MainWindow::on_pushButton_img_clicked()
{QString buttonText = ui->pushButton_img->text();qDebug() << "点击的按钮内容是: " << buttonText;QString fileName = QFileDialog::getOpenFileName(this, "选择图片", "", "图片文件 (*.png *.jpg *.jpeg)");if (!fileName.isEmpty()) {ui->widget->loadImage(fileName); // 调用 loadImage 函数加载图片}
}
点击运行程序

6、绘制不同图形进行选择
修改paintEvent代码
void DrawingWidget::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);QPainter painter(this);// 绘制图像if (!m_image.isNull()) {painter.drawImage(0, 0, m_image);}// 根据当前绘制类型绘制不同的图形switch (m_currentPaintType) {case 0: // 绘制矩形painter.setPen(Qt::red);painter.drawRect(50, 50, 100, 100);break;case 1: { // 使用花括号限制变量作用域QPolygon polygon;polygon << QPoint(50, 50) << QPoint(150, 50) << QPoint(100, 150);painter.setPen(Qt::blue);painter.drawPolygon(polygon);break;}case 2: // 绘制线条painter.setPen(Qt::green);painter.drawLine(50, 50, 150, 150);break;default:break;}
}
添加函数void painttype(int type);
ui->widget->painttype(0);//绘制矩形
ui->widget->painttype(1);//绘制三角形
ui->widget->painttype(2);//绘制线条
添加到按键槽函数当中,点击俺家就能实现

代码
// DrawingWidget.h
#ifndef DRAWINGWIDGET_H
#define DRAWINGWIDGET_H#include <QWidget>
#include <QImage>class DrawingWidget : public QWidget
{Q_OBJECT
public:explicit DrawingWidget(QWidget *parent = nullptr);~DrawingWidget();void loadImage(const QString &fileName);void paintEvent(QPaintEvent *event) override;void painttype(int type);private:QImage m_image;int m_currentPaintType; // 记录当前要绘制的图形类型
};#endif // DRAWINGWIDGET_H
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_img_clicked(); // 声明槽函数void on_pushButton_Rectangle_clicked(); // 声明槽函数void on_pushButton_IrregularShape_clicked(); // 声明槽函数void on_pushButton_Line_clicked(); // 声明槽函数private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
// DrawingWidget.cpp
#include "DrawingWidget.h"
#include <QPainter>
#include <QPolygon>
#include <QPoint>DrawingWidget::DrawingWidget(QWidget *parent) : QWidget(parent)
{QPalette palette = this->palette();palette.setColor(QPalette::Window, Qt::black);this->setAutoFillBackground(true);this->setPalette(palette);m_currentPaintType =-1;
}DrawingWidget::~DrawingWidget()
{
}void DrawingWidget::loadImage(const QString &fileName)
{if (m_image.load(fileName)) {qDebug() << "图片加载成功: " << fileName;update();} else {qDebug() << "图片加载失败: " << fileName;}}void DrawingWidget::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);QPainter painter(this);// 绘制图像if (!m_image.isNull()) {painter.drawImage(0, 0, m_image);}// 根据当前绘制类型绘制不同的图形switch (m_currentPaintType) {case 0: // 绘制矩形painter.setPen(Qt::red);painter.drawRect(50, 50, 100, 100);break;case 1: { // 使用花括号限制变量作用域QPolygon polygon;polygon << QPoint(50, 50) << QPoint(150, 50) << QPoint(100, 150);painter.setPen(Qt::blue);painter.drawPolygon(polygon);break;}case 2: // 绘制线条painter.setPen(Qt::green);painter.drawLine(50, 50, 150, 150);break;default:break;}
}void DrawingWidget::painttype(int type)
{m_currentPaintType = type;update(); // 重新绘制界面
}
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "DrawingWidget.h"
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_img_clicked()
{QString buttonText = ui->pushButton_img->text();qDebug() << "点击的按钮内容是: " << buttonText;QString fileName = QFileDialog::getOpenFileName(this, "选择图片", "", "图片文件 (*.png *.jpg *.jpeg)");if (!fileName.isEmpty()) {ui->widget->loadImage(fileName); // 调用 loadImage 函数加载图片}
}void MainWindow::on_pushButton_Rectangle_clicked()
{QString buttonText = ui->pushButton_Rectangle->text();qDebug() << "点击的按钮内容是: " << buttonText;ui->widget->painttype(0);
}void MainWindow::on_pushButton_IrregularShape_clicked()
{QString buttonText = ui->pushButton_IrregularShape->text();qDebug() << "点击的按钮内容是: " << buttonText;ui->widget->painttype(1);
}void MainWindow::on_pushButton_Line_clicked()
{QString buttonText = ui->pushButton_Line->text();qDebug() << "点击的按钮内容是: " << buttonText;ui->widget->painttype(2);}
//main.cpp
#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
总结
1、自定义控件,控件提升
2、槽函数自动关联
3、加载图片
4、重写函数:void paintEvent(QPaintEvent *event) override;
提升
直接绘制图形,修改为鼠标绘制
相关文章:
QT:图像上绘制图形
需求描述 1、展示一张图像 2、在图像上可以使用数据绘制图像:矩形、不规则图形、线条 3、有按键可以选择 概要设计 规划布局如下 1、左边是Qlabel 用于展示图片 2、右边是三个按钮 具体实现 1、 首先设计 UI 界面,对控件进行布局 在 mainwindow.u…...
GPU上没程序在跑但是显存被占用
原因:存在僵尸线程,运行完但是没有释放内存 查看僵尸线程 fuser -v /dev/nvidia*关闭僵尸线程 pkill -9 -u 用户名 程序名 举例:pkill -9 -u grs python参考:https://blog.csdn.net/qq_40206371/article/details/143798866...
wordpress代码结构解析
WordPress 是一个基于 PHP 和 MySQL 的开源内容管理系统(CMS),广泛用于构建网站和博客。要解析 WordPress 代码,首先需要了解其核心结构、主要文件和常用的函数。以下是 WordPress 代码解析的基本指南: --- ### 1. *…...
【Unity3D】实现2D小地图效果
目录 一、玩家脚本Player 二、Canvas组件设置 三、小地图相关 四、GameLogicMap脚本修改 基于:【Unity3D】Tilemap俯视角像素游戏案例-CSDN博客 2D玩家添加Dotween移动DOPath效果,移动完成后进行刷新小地图(小地图会顺便刷新大地图&…...
关联传播和 Python 和 Scikit-learn 实现
文章目录 一、说明二、什么是 Affinity Propagation。2.1 先说Affinity 传播的工作原理2.2 更多细节2.3 传播两种类型的消息2.4 计算责任和可用性的分数2.4.1 责任2.4.2 可用性分解2.4.3 更新分数:集群是如何形成的2.4.4 估计集群本身的数量。 三、亲和力传播的一些…...
https数字签名手动验签
以bing.com 为例 1. CA 层级的基本概念 CA 层级是一种树状结构,由多个层级的 CA 组成。每个 CA 负责为其下一层级的实体(如子 CA 或终端实体)颁发证书。层级结构的顶端是 根 CA(Root CA),它是整个 PKI 体…...
LeetCode:62.不同路径
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:62.不同路径 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” &…...
如果我想设计一款复古风格的壁纸,应该选什么颜色?
设计复古风格的壁纸时,选择合适的颜色是营造怀旧和经典氛围的关键。复古风格通常使用一些温暖、柔和且带有岁月痕迹的色调。以下是一些适合复古风格壁纸的颜色选择和搭配建议: 一、复古风格的主色调 棕色系: 特点:棕色是复古风格的…...
【数据结构】树的基本:结点、度、高度与计算
树是数据结构中一种重要的非线性结构,广泛应用于计算机科学的各个领域,例如文件系统、数据库索引、编译器等。理解树的各种性质,如结点数、度、高度等,对于解决实际问题至关重要。 本文将会探讨树的基本概念,以及给出几…...
【Pytest】生成html报告中,中文乱码问题解决方案
链接上一篇文章:https://blog.csdn.net/u013080870/article/details/145369926?spm1001.2014.3001.5502 中文乱码问题,python3,Python3.7后,还一个文件就是result.py 因为中文可以在内容中,也可能在文件名,类名&…...
week08_文本匹配任务
1、文本匹配任务概述 狭义: 给定一组文本,判断其是否语义相似 今天天气不错 match 今儿个天不错呀 √ 今天天气不错 match 你的代码有bug 以分值形式给出相似度 今天天气不错 match 今儿个天不错呀 0.9 今天天气不错 match…...
JUC--ConcurrentHashMap底层原理
ConcurrentHashMap底层原理 ConcurrentHashMapJDK1.7底层结构线程安全底层具体实现 JDK1.8底层结构线程安全底层具体实现 总结JDK 1.7 和 JDK 1.8实现有什么不同?ConcurrentHashMap 中的 CAS 应用 ConcurrentHashMap ConcurrentHashMap 是一种线程安全的高效Map集合…...
【2024年华为OD机试】(C卷,200分)- 推荐多样性 (JavaScriptJava PythonC/C++)
一、问题描述 问题描述 我们需要从多个已排序的列表中选取元素,以填充多个窗口。每个窗口需要展示一定数量的元素,且元素的选择需要遵循特定的穿插策略。具体来说,我们需要: 从第一个列表中为每个窗口选择一个元素,然后从第二个列表中为每个窗口选择一个元素,依此类推。…...
【教学类-89-01】20250127新年篇01—— 蛇年红包(WORD模版)
祈愿在2025蛇年里, 伟大的祖国风调雨顺、国泰民安、每个人齐心协力,共同经历这百年未有之大变局时代(国际政治、AI技术……) 祝福亲友同事孩子们平安健康(安全、安全、安全)、巳巳如意! 背景需…...
[权限提升] 操作系统权限介绍
关注这个专栏的其他相关笔记:[内网安全] 内网渗透 - 学习手册-CSDN博客 权限提升简称提权,顾名思义就是提升自己在目标系统中的权限。现在的操作系统都是多用户操作系统,用户之间都有权限控制,我们通过 Web 漏洞拿到的 Web 进程的…...
DeepSeek异军突起,重塑AI格局
DeepSeek异军突起,重塑AI格局这两天AI 圈发生了比过年更令人兴奋的事情,“Meta内部反水事件”、“黄仁勋的底盘问题”,以及AI格局的大动荡,一切都是因为那个叫DeepSeek的“中国自主AI”!它由幻方量化开发,以…...
git的理解与使用
本地的git git除了最经典的add commit push用来做版本管理,其实他的分支管理也非常强大 可以说你学好了分支管理,就可以完成团队的配合协作了 git仓库 我们可以使用git init来初始化一个git仓库,只要能看见.git文件夹,就代表这…...
Baklib打造内容中台新模式助力企业智能化升级
内容概要 在如今数字化日渐渗透各个行业的背景下,内容中台逐渐成为推动企业智能化转型的重要工具。内容中台不仅仅是一个信息管理平台,更是一个整合多种内容资源,提升企业反应能力与市场适应力的创新模式。随着数据量的激增,传统…...
STM32完全学习——RT-thread在STM32F407上移植
一、写在前面 关于源码的下载,以及在KEIL工程里面添加操作系统的源代码,这里就不再赘述了。需要注意的是RT-thread默认里面是会使用串口的,因此需要额外的进行串口的初始化,有些人可能会问,为什么不直接使用CubMAX直接…...
基于51单片机和ESP8266(01S)、LCD1602、DS1302、独立按键的WiFi时钟
目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、延时2、定时器03、串口通信4、DS13025、LCD16026、独立按键 四、主函数总结 系列文章目录 前言 之前做了一个WiFi定时器时钟,用八位数码管进行显示,但是定时器时钟的精度较低࿰…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
