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

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…...

基于java线程池和EasyExcel实现数据异步导入

基于java线程池和EasyExcel实现数据异步导入 2.代码实现 2.1 controller层 PostMapping("import")public void importExcel(MultipartFile file) throws IOException {importService.importExcelAsync(file);}2.2 service层 Resource private SalariesListener sa…...

HPO3:提升模型性能的高效超参数优化工具

引言 在当今快速发展的数据科学和机器学习领域中&#xff0c;超参数优化&#xff08;Hyperparameter Optimization, HPO&#xff09;是构建高性能模型不可或缺的一环。为了简化这一复杂过程&#xff0c;恒通网络科技团队推出了HPO3模块——一个专为Python开发者设计的强大库&a…...

重回C语言之老兵重装上阵(十五)C语言错误处理

C语言错误处理 在C语言中&#xff0c;错误处理是非常重要的一部分。C语言没有像高级语言&#xff08;例如Python、Java&#xff09;那样内建的异常处理机制&#xff08;如try-catch&#xff09;&#xff0c;但它提供了几种方法来捕捉和处理错误。正确的错误处理可以提高程序的稳…...

使用国内镜像加速器解决 Docker Hub 拉取镜像慢或被屏蔽的问题

一、问题背景 Docker Hub 是 Docker 默认的镜像仓库&#xff0c;但由于网络限制&#xff0c;国内用户直接拉取镜像可能面临以下问题&#xff1a; 下载速度极慢&#xff08;尤其是大镜像&#xff09;。连接超时或完全被屏蔽&#xff08;部分网络环境&#xff09;。依赖国外源的…...

为AI聊天工具添加一个知识系统 之76 详细设计之17 正则表达式 之4 正则表达式模板

Q712、三“化” &#xff08;使用三种不同的定义方法&#xff1a;规定定义法 -线性回归/内涵定义法--一阶迭代/外延定义法--单调递归&#xff09; 整体形成 一个双人零和 的局面 <Class()外延式, Type()内涵式> Method()规定式。给出 问题“law 是什么”的三种答案&#…...

日志收集Day007

1.配置ES集群TLS认证: (1)elk101节点生成证书文件 cd /usr/share/elasticsearch ./bin/elasticsearch-certutil cert -out config/elastic-certificates.p12 -pass "" --days 3650 (2)elk101节点为证书文件修改属主和属组 chown elasticsearch:elasticsearch con…...

【Python】 使用pygame库实现新年烟花

祝大家金蛇衔财&#xff0c;蛇来运转 首先&#xff0c;确保你已经安装了 pygame 库。如果还没有安装&#xff0c;可以通过以下命令安装&#xff1a; pip install pygame接下来是烟花效果的 Python 代码&#xff1a; import pygame import random import math import sys# 初始…...

C语言中string.h头文件功能介绍

在C语言的世界里&#xff0c;string.h头文件提供了许多用于处理字符串和内存操作的函数。今天&#xff0c;我们就来深入探讨string.h头文件的功能、使用注意事项以及一些拓展应用。 一、功能介绍 string.h头文件定义了一系列用于操作字符串和内存的函数。这些函数可以分为几个…...

群晖docker获取私有化镜像http: server gave HTTP response to HTTPS client].

群晖docker获取私有化镜像提示http: server gave HTTP response to HTTPS clien 问题描述 层级时间用户事件Information2023/07/08 12:47:45cxlogeAdd image from xx.xx.31.240:1923/go-gitea/gitea:1.19.3Error2023/07/08 12:47:48cxlogeFailed to pull image [Get "http…...

react antd点击table单元格文字下载指定的excel路径

在使用 Ant Design (antd) 的 Table 组件时&#xff0c;如果想点击表格单元格中的文字来触发下载指定路径的 Excel 文件&#xff0c;可以通过以下步骤实现&#xff1a; 1. 确保有一个可供下载的 Excel 文件&#xff1a;需要有一个服务器端点或者一个可以直接访问的 URL&#xf…...

《哈佛家训》

《哈佛家训》是2010年由威廉贝纳德撰写&#xff0c;张玉翻译&#xff0c;在中国妇女出版社出版的专著。书中有许多富有哲理的故事&#xff0c;传达了诸多教育理念和人生智慧&#xff0c;以下是一些例子及相应启示&#xff1a; ### 眼界与格局方面 - **故事**&#xff1a;小伙子…...

ResNeSt: Split-Attention Networks论文学习笔记

这张图展示了一个名为“Split-Attention”的神经网络结构&#xff0c;该结构在一个基数组&#xff08;cardinal group&#xff09;内进行操作。基数组通常指的是在神经网络中处理的一组特征或通道。图中展示了如何通过一系列操作来实现对输入特征的注意力机制。 以下是图中各部…...

【matlab】绘图 离散数据--->连续函数

matlab绘图练习 离散数据及离散函数对离散区间进行细划分 达到连续效果画plot(y)图 与 复数的应用 离散数据及离散函数 例1 x1[1 2 4 6 7 8 10 11 12 14 16 17 18 20] y1[1 2 4 6 7 8 10 10 8 7 6 4 2 1] figure(1); plot(x1,y1,o,MarkerSize,15); x21:20; y2log(x2); figure…...

pyside6-uic form.ui -o ui_form.py 的作用

pyside6-uic form.ui -o ui_form.py 的作用 pyside6-uic form.ui -o ui_form.py 这个命令是用来将 .ui 文件转换为 Python 代码文件的工具。 具体作用&#xff1a; pyside6-uic&#xff1a;这是一个命令行工具&#xff0c;用于将用 Qt Designer 或其他图形界面工具创建的 .ui …...

Qt中QVariant的使用

1.使用QVariant实现不同类型数据的相加 方法&#xff1a;通过type函数返回数值的类型&#xff0c;然后通过setValue来构造一个QVariant类型的返回值。 函数&#xff1a; QVariant mainPage::dataPlus(QVariant a, QVariant b) {QVariant ret;if ((a.type() QVariant::Int) &a…...

基础项目实战——3D赛车(c++)

目录 前言一、渲染引擎二、关闭事件三、梯形绘制四、轨道绘制五、边缘绘制六、草坪绘制七、前后移动八、左右移动​九、曲线轨道​十、课山坡轨道​十一、循环轨道​十二、背景展示​十三、引入速度​十四、物品绘制​十五、课数字路障​十六、分数展示​十七、重新生成​十八、…...

【SpringBoot教程】Spring Boot + MySQL + HikariCP 连接池整合教程

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 在前面一篇文章中毛毛张介绍了SpringBoot中数据源与数据库连接池相关概念&#xff0c;今天毛毛张要分享的是关于SpringBoot整合HicariCP连接池相关知识点以及底层源码…...

每日一题 430. 扁平化多级双向链表

430. 扁平化多级双向链表 简单 /*class Solution { public:Node* flatten(Node* head) {Node* tail nullptr;return dfs(head);}Node* dfs(Node* head){Node* cur head;while(cur ! nullptr){if(cur->child ! nullptr){Node* curChild getTail(cur->child);Node* te…...

vue3表格数据分2个表格序号连续展示

一、el-table表格在弹窗里面分两个表格展示。 假设我们有一个数组 tableData&#xff0c;我们希望在第一个表格中展示前半部分的数据&#xff0c;第二个表格中展示后半部分的数据。 <template><el-button type"primary" click"dialogVisible true&q…...

【愚公系列】《循序渐进Vue.js 3.x前端开发实践》027-组件的高级配置和嵌套

标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...

一文讲解Java中Object类常用的方法

在Java中&#xff0c;经常提到一个词“万物皆对象”&#xff0c;其中的“万物”指的是Java中的所有类&#xff0c;而这些类都是Object类的子类&#xff1b; Object主要提供了11个方法&#xff0c;大致可以分为六类&#xff1a; 对象比较&#xff1a; public native int has…...

操作系统之输入输出

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

【Convex Optimization Stanford】Lec3 Function

【Convex Optimization Stanford】Lec3 Function 前言凸函数的定义对凸函数在一条线上的限制增值扩充&#xff1f; 一阶条件二阶条件一些一阶/二阶条件的例子象集和sublevel set关于函数凸性的扩展&#xff08;Jesen Inequality)保持函数凸性的操作非负加权和 & 仿射函数的…...

【Linux探索学习】第二十七弹——信号(一):Linux 信号基础详解

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 前面我们已经将进程通信部分讲完了&#xff0c;现在我们来讲一个进程部分也非常重要的知识点——信号&#xff0c;信号也是进程间通信的一…...

SpringBoot或SpringAI对接DeekSeek大模型

今日除夕夜&#xff0c;deepseek可是出尽了风头&#xff0c;但是我看网上还没有这方面的内容对接&#xff0c;官网也并没有&#xff0c;故而本次对接是为了完成这个空缺 我看很多的博客内容是流式请求虽然返回时正常的&#xff0c;但是他并不是实时返回&#xff0c;而是全部响应…...

Funnel-Transformer:通过过滤序列冗余实现高效语言处理

摘要 随着语言预训练的成功&#xff0c;开发更具扩展性且能高效利用大量未标注数据的架构变得尤为重要。为了提高效率&#xff0c;我们研究了在维持完整token级别表示时的冗余问题&#xff0c;尤其是对于仅需要序列单向量表示的任务。基于这一直觉&#xff0c;我们提出了Funne…...

【搜索回溯算法】:BFS的魔力--如何使用广度优先搜索找到最短路径

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;搜索回溯算法篇–CSDN博客 文章目录 一.广度优先搜索&#xff08;BFS&#xff09;解决最短路…...

【算法】经典博弈论问题——威佐夫博弈 python

目录 威佐夫博弈(Wythoff Game)【模板】 威佐夫博弈(Wythoff Game) 有两堆石子&#xff0c;数量任意&#xff0c;可以不同&#xff0c;游戏开始由两个人轮流取石子 游戏规定&#xff0c;每次有两种不同的取法 1)在任意的一堆中取走任意多的石子 2)可以在两堆中同时取走相同数量…...

CUDA学习-内存访问

一 访存合并 1.1 说明 本部分内容主要参考: 搞懂 CUDA Shared Memory 上的 bank conflicts 和向量化指令(LDS.128 / float4)的访存特点 - 知乎 1.2 share memory结构 图1.1 share memory结构 放在 shared memory 中的数据是以 4 bytes(即 32 bits)作为 1 个 word,依…...