当前位置: 首页 > 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_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    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.kler.cn/a/522953.html

相关文章:

  • 什么是长短期记忆网络?
  • Vscode的AI插件 —— Cline
  • 项目集成Nacos
  • 【落羽的落羽 数据结构篇】顺序表
  • 穷举vs暴搜vs深搜vs回溯vs剪枝系列一>解数独
  • OpenCV:图像处理中的低通滤波
  • 基于Django的个人博客系统的设计与实现
  • 【现代深度学习技术】深度学习计算 | 参数管理
  • Flink (十三) :Table API 与 DataStream API 的转换 (一)
  • TypeScript 学习 -类型 - 9
  • MySQL知识点总结(十二)
  • 树和图的实现与应用:C语言实践详解
  • Docker/K8S
  • C语言中的do……while和while循环有什么区别?
  • MySQL事物,MVCC机制
  • 【搜索回溯算法篇】:多源BFS--从简单BFS到多点协同,探索搜索算法的进化
  • 挂载mount
  • 可扩展架构:如何打造一个善变的柔性系统?
  • LTV预估 | 多视角对比学习框架CMLTV
  • 四层网络模型
  • mybatis(112/134)
  • Windows 程序设计5:文件的删除、复制与重命名操作
  • JVM栈溢出线上环境排查
  • 基于Ubuntu交叉编译ZLMediaKit
  • PCB Editor层叠文件(Gerber文件输出-01)
  • 【自然语言处理(NLP)】机器翻译之数据处理(数据收集、数据清洗、数据分词、数据标注、数据划分)