QT:图像上绘制图形

embedded/2025/2/2 5:38:09/

需求描述

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;

提升

直接绘制图形,修改为鼠标绘制


http://www.ppmy.cn/embedded/158824.html

相关文章

Github 2025-01-25Rust开源项目日报Top10

根据Github Trendings的统计,今日(2025-01-25统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Python项目1Vue项目1JavaScript项目1Deno: 现代JavaScript和TypeScript运行时 创建周期:2118 天开发语言:Rust, JavaScript协议类型…

Redis脑裂问题详解及解决方案

Redis是一种高性能的内存数据库&#xff0c;广泛应用于缓存、消息队列等场景。然而&#xff0c;在分布式Redis集群中&#xff0c;脑裂问题&#xff08;Split-Brain&#xff09;是一个需要特别关注的复杂问题。本文将详细介绍Redis脑裂问题的成因、影响及解决方案。 一、什么是…

uniapp商城项目之商品详情

文章目录 一、商品详情组件1.新建页面并处理参数2.封装API接口5.初始化调用 二、轮播图交互1.更新下标2.放大预览 三、弹出层组件交互1.弹出层组件2.实现交互 一、商品详情组件 1.新建页面并处理参数 pages下新建一个文件夹goods——> goods.vue&#xff0c;在分类categor…

深度学习|表示学习|卷积神经网络|输出维度公式|15

如是我闻&#xff1a; 在卷积和池化操作中&#xff0c;计算输出维度的公式是关键&#xff0c;它们分别可以帮助我们计算卷积操作和池化操作后的输出大小。下面分别总结公式&#xff0c;并结合解释它们的意义&#xff1a; 1. 卷积操作的输出维度公式 当我们对输入图像进行卷积时…

Python 类型注解

文章目录 Python 类型注解详解1. 引言2. Python 类型注解基础2.1 变量类型注解2.2 函数参数和返回值注解2.3 typing 模块的支持 3. 进阶&#xff1a;复杂数据类型3.1 可选类型&#xff08;Optional&#xff09;3.2 联合类型&#xff08;Union&#xff09;3.3 泛型&#xff08;G…

python 使用Whisper模型进行语音翻译

目录 一、Whisper 是什么? 二、Whisper 的基本命令行用法 三、代码实践 四、是否保留Token标记 五、翻译长度问题 六、性能分析 一、Whisper 是什么? Whisper 是由 OpenAI 开源的一个自动语音识别(Automatic Speech Recognition, ASR)系统。它的主要特点是: 多语言…

JavaScript系列(52)--编译优化技术详解

JavaScript编译优化技术详解 &#x1f680; 今天&#xff0c;让我们深入探讨JavaScript的编译优化技术。通过理解和应用这些技术&#xff0c;我们可以显著提升JavaScript代码的执行效率。 编译优化基础概念 &#x1f31f; &#x1f4a1; 小知识&#xff1a;JavaScript引擎通常…

关于Java的HttpURLConnection重定向问题 响应码303

我有一个Java函数&#xff0c;发送了一个POST请求&#xff0c;并获取响应头的Headers&#xff0c;使用 java.net.http 库能正常运行。 伪代码如下 private static String loginPhone() throws Exception {String url1 "https://api-user.xxx";String data1 Strin…