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

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、在图像上可以使用数据绘制图像&#xff1a;矩形、不规则图形、线条 3、有按键可以选择 概要设计 规划布局如下 1、左边是Qlabel 用于展示图片 2、右边是三个按钮 具体实现 1、 首先设计 UI 界面&#xff0c;对控件进行布局 在 mainwindow.u…...

GPU上没程序在跑但是显存被占用

原因&#xff1a;存在僵尸线程&#xff0c;运行完但是没有释放内存 查看僵尸线程 fuser -v /dev/nvidia*关闭僵尸线程 pkill -9 -u 用户名 程序名 举例&#xff1a;pkill -9 -u grs python参考&#xff1a;https://blog.csdn.net/qq_40206371/article/details/143798866...

wordpress代码结构解析

WordPress 是一个基于 PHP 和 MySQL 的开源内容管理系统&#xff08;CMS&#xff09;&#xff0c;广泛用于构建网站和博客。要解析 WordPress 代码&#xff0c;首先需要了解其核心结构、主要文件和常用的函数。以下是 WordPress 代码解析的基本指南&#xff1a; --- ### 1. *…...

【Unity3D】实现2D小地图效果

目录 一、玩家脚本Player 二、Canvas组件设置 三、小地图相关 四、GameLogicMap脚本修改 基于&#xff1a;【Unity3D】Tilemap俯视角像素游戏案例-CSDN博客 2D玩家添加Dotween移动DOPath效果&#xff0c;移动完成后进行刷新小地图&#xff08;小地图会顺便刷新大地图&…...

关联传播和 Python 和 Scikit-learn 实现

文章目录 一、说明二、什么是 Affinity Propagation。2.1 先说Affinity 传播的工作原理2.2 更多细节2.3 传播两种类型的消息2.4 计算责任和可用性的分数2.4.1 责任2.4.2 可用性分解2.4.3 更新分数&#xff1a;集群是如何形成的2.4.4 估计集群本身的数量。 三、亲和力传播的一些…...

https数字签名手动验签

以bing.com 为例 1. CA 层级的基本概念 CA 层级是一种树状结构&#xff0c;由多个层级的 CA 组成。每个 CA 负责为其下一层级的实体&#xff08;如子 CA 或终端实体&#xff09;颁发证书。层级结构的顶端是 根 CA&#xff08;Root CA&#xff09;&#xff0c;它是整个 PKI 体…...

LeetCode:62.不同路径

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;62.不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &…...

如果我想设计一款复古风格的壁纸,应该选什么颜色?

设计复古风格的壁纸时&#xff0c;选择合适的颜色是营造怀旧和经典氛围的关键。复古风格通常使用一些温暖、柔和且带有岁月痕迹的色调。以下是一些适合复古风格壁纸的颜色选择和搭配建议&#xff1a; 一、复古风格的主色调 棕色系&#xff1a; 特点&#xff1a;棕色是复古风格的…...

【数据结构】树的基本:结点、度、高度与计算

树是数据结构中一种重要的非线性结构&#xff0c;广泛应用于计算机科学的各个领域&#xff0c;例如文件系统、数据库索引、编译器等。理解树的各种性质&#xff0c;如结点数、度、高度等&#xff0c;对于解决实际问题至关重要。 本文将会探讨树的基本概念&#xff0c;以及给出几…...

【Pytest】生成html报告中,中文乱码问题解决方案

链接上一篇文章:https://blog.csdn.net/u013080870/article/details/145369926?spm1001.2014.3001.5502 中文乱码问题&#xff0c;python3&#xff0c;Python3.7后&#xff0c;还一个文件就是result.py 因为中文可以在内容中&#xff0c;也可能在文件名&#xff0c;类名&…...

week08_文本匹配任务

1、文本匹配任务概述 狭义&#xff1a; 给定一组文本&#xff0c;判断其是否语义相似 今天天气不错 match 今儿个天不错呀 √ 今天天气不错 match 你的代码有bug 以分值形式给出相似度 今天天气不错 match 今儿个天不错呀 0.9 今天天气不错 match…...

JUC--ConcurrentHashMap底层原理

ConcurrentHashMap底层原理 ConcurrentHashMapJDK1.7底层结构线程安全底层具体实现 JDK1.8底层结构线程安全底层具体实现 总结JDK 1.7 和 JDK 1.8实现有什么不同&#xff1f;ConcurrentHashMap 中的 CAS 应用 ConcurrentHashMap ConcurrentHashMap 是一种线程安全的高效Map集合…...

【2024年华为OD机试】(C卷,200分)- 推荐多样性 (JavaScriptJava PythonC/C++)

一、问题描述 问题描述 我们需要从多个已排序的列表中选取元素,以填充多个窗口。每个窗口需要展示一定数量的元素,且元素的选择需要遵循特定的穿插策略。具体来说,我们需要: 从第一个列表中为每个窗口选择一个元素,然后从第二个列表中为每个窗口选择一个元素,依此类推。…...

【教学类-89-01】20250127新年篇01—— 蛇年红包(WORD模版)

祈愿在2025蛇年里&#xff0c; 伟大的祖国风调雨顺、国泰民安、每个人齐心协力&#xff0c;共同经历这百年未有之大变局时代&#xff08;国际政治、AI技术……&#xff09; 祝福亲友同事孩子们平安健康&#xff08;安全、安全、安全&#xff09;、巳巳如意&#xff01; 背景需…...

[权限提升] 操作系统权限介绍

关注这个专栏的其他相关笔记&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 权限提升简称提权&#xff0c;顾名思义就是提升自己在目标系统中的权限。现在的操作系统都是多用户操作系统&#xff0c;用户之间都有权限控制&#xff0c;我们通过 Web 漏洞拿到的 Web 进程的…...

DeepSeek异军突起,重塑AI格局

DeepSeek异军突起&#xff0c;重塑AI格局这两天AI 圈发生了比过年更令人兴奋的事情&#xff0c;“Meta内部反水事件”、“黄仁勋的底盘问题”&#xff0c;以及AI格局的大动荡&#xff0c;一切都是因为那个叫DeepSeek的“中国自主AI”&#xff01;它由幻方量化开发&#xff0c;以…...

git的理解与使用

本地的git git除了最经典的add commit push用来做版本管理&#xff0c;其实他的分支管理也非常强大 可以说你学好了分支管理&#xff0c;就可以完成团队的配合协作了 git仓库 我们可以使用git init来初始化一个git仓库&#xff0c;只要能看见.git文件夹&#xff0c;就代表这…...

Baklib打造内容中台新模式助力企业智能化升级

内容概要 在如今数字化日渐渗透各个行业的背景下&#xff0c;内容中台逐渐成为推动企业智能化转型的重要工具。内容中台不仅仅是一个信息管理平台&#xff0c;更是一个整合多种内容资源&#xff0c;提升企业反应能力与市场适应力的创新模式。随着数据量的激增&#xff0c;传统…...

STM32完全学习——RT-thread在STM32F407上移植

一、写在前面 关于源码的下载&#xff0c;以及在KEIL工程里面添加操作系统的源代码&#xff0c;这里就不再赘述了。需要注意的是RT-thread默认里面是会使用串口的&#xff0c;因此需要额外的进行串口的初始化&#xff0c;有些人可能会问&#xff0c;为什么不直接使用CubMAX直接…...

基于51单片机和ESP8266(01S)、LCD1602、DS1302、独立按键的WiFi时钟

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、延时2、定时器03、串口通信4、DS13025、LCD16026、独立按键 四、主函数总结 系列文章目录 前言 之前做了一个WiFi定时器时钟&#xff0c;用八位数码管进行显示&#xff0c;但是定时器时钟的精度较低&#xff0…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...