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

03.05 QT事件

实现一个绘图工具,具备以下功能:

  • 鼠标绘制线条。

  • 实时调整线条颜色和粗细。

  • 橡皮擦功能,覆盖绘制内容。

  • 撤销功能,ctrl + z 快捷键撤销最后一笔

程序代码:
<1> Widget.h:
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QDebug>
#include <QMouseEvent>
#include <QLine>
#include <QVector>
#include <QColorDialog>
#include <QPair>
#include <QKeyEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    QPoint start;
    QPoint end;
    QVector<QVector<QPair<QLine, QPair<QColor, int>>>> strokes; // 存储每一笔的所有线段
    QVector<QPair<QLine, QPair<QColor, int>>> currentStroke;    // 当前正在绘制的一笔
    QColor currentColor = Qt::black;                            // 当前颜色
    int currentWidth = 1;                                        // 当前线条粗细
    bool isEraserMode = false;                                   // 是否为橡皮擦模式

protected:
    virtual void paintEvent(QPaintEvent *event) override;
    virtual void mouseMoveEvent(QMouseEvent *event) override;
    virtual void mousePressEvent(QMouseEvent *event) override;
    virtual void mouseReleaseEvent(QMouseEvent *event) override;
    virtual void keyPressEvent(QKeyEvent *event) override; // 键盘事件处理

private slots:
    void on_pushButton_clicked(); // 调色板
    void on_pushButton_2_clicked(); // 1mm
    void on_pushButton_3_clicked(); // 5mm
    void on_pushButton_4_clicked(); // 10mm
    void on_pushButton_6_clicked(); // 20mm
    void on_pushButton_5_clicked(); // 橡皮擦
};
#endif // WIDGET_H
<2> Widget.cpp:
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setPalette(QPalette(Qt::white)); // 设置窗口背景色为白色
    setAutoFillBackground(true);     // 自动填充背景
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPen pen;

    // 遍历所有笔触,绘制每一笔
    for (const auto &stroke : strokes) {
        for (const auto &linePair : stroke) {
            pen.setColor(linePair.second.first); // 设置线条颜色
            pen.setWidth(linePair.second.second); // 设置线条粗细
            painter.setPen(pen);
            painter.drawLine(linePair.first); // 绘制线条
        }
    }

    // 绘制当前正在绘制的一笔
    for (const auto &linePair : currentStroke) {
        pen.setColor(linePair.second.first); // 设置线条颜色
        pen.setWidth(linePair.second.second); // 设置线条粗细
        painter.setPen(pen);
        painter.drawLine(linePair.first); // 绘制线条
    }
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        end = event->pos();
        QLine line(start, end);

        // 如果是橡皮擦模式,使用背景色绘制
        if (isEraserMode) {
            QColor backgroundColor = palette().color(QPalette::Window); // 获取窗口背景色
            currentStroke << qMakePair(line, qMakePair(backgroundColor, currentWidth)); // 使用背景色覆盖
        } else {
            currentStroke << qMakePair(line, qMakePair(currentColor, currentWidth)); // 正常绘制
        }

        start = end;
        update(); // 触发重绘
    }
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        start = event->pos(); // 记录起点
        currentStroke.clear(); // 开始新的一笔
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        end = event->pos();
        QLine line(start, end);

        // 如果是橡皮擦模式,使用背景色绘制
        if (isEraserMode) {
            QColor backgroundColor = palette().color(QPalette::Window); // 获取窗口背景色
            currentStroke << qMakePair(line, qMakePair(backgroundColor, currentWidth)); // 使用背景色覆盖
        } else {
            currentStroke << qMakePair(line, qMakePair(currentColor, currentWidth)); // 正常绘制
        }

        strokes << currentStroke; // 将当前一笔添加到所有笔触中
        currentStroke.clear(); // 清空当前一笔
        update(); // 触发重绘
    }
}

// 键盘事件处理
void Widget::keyPressEvent(QKeyEvent *event)
{
    // 检测 Ctrl + Z 按键组合
    if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_Z) {
        if (!strokes.isEmpty()) {
            strokes.removeLast(); // 移除最后一整笔
            update(); // 触发重绘
        }
    }
}

// 打开调色板
void Widget::on_pushButton_clicked()
{
    currentColor = QColorDialog::getColor(currentColor, this, "选择颜色");
}

void Widget::on_pushButton_2_clicked()
{
    currentWidth = 1; // 设置线条粗细为 1
}

void Widget::on_pushButton_3_clicked()
{
    currentWidth = 5; // 设置线条粗细为 5
}

void Widget::on_pushButton_4_clicked()
{
    currentWidth = 10; // 设置线条粗细为 10
}

void Widget::on_pushButton_6_clicked()
{
    currentWidth = 20; // 设置线条粗细为 20
}

// 切换橡皮擦模式
void Widget::on_pushButton_5_clicked()
{
    isEraserMode = !isEraserMode; // 切换橡皮擦模式
    if (isEraserMode) {
        ui->pushButton_5->setText("绘图模式"); // 更新按钮文本
    } else {
        ui->pushButton_5->setText("橡皮擦"); // 更新按钮文本
    }
}
<3> main.cpp:
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}


http://www.kler.cn/a/579181.html

相关文章:

  • uniapp uniCloud引发的血案(switchTab: Missing required args: “url“)!!!!!!!!!!
  • 力扣72题编辑距离
  • Linux运维——oh-my-zsh
  • 高效处理 List<T> 集合:更新、查找与优化技巧
  • 《A++ 敏捷开发》- 18 软件需求
  • HTML 文本格式化
  • Python爬取咸鱼Goodfish店铺所有商品接口的详细指南
  • Android中的Fragment是什么以及它有哪些生命周期方法
  • unity学习64,第3个小游戏:一个2D跑酷游戏
  • react基本功
  • 【漫话机器学习系列】121.偏导数(Partial Derivative)
  • 【springcloud】快速搭建一套分布式服务springcloudalibaba(二)
  • 前端常用布局
  • Deeplabv3+改进4:在主干网络中添加GAMAattention|助力涨点!
  • Python实现鼠标点击获取窗口进程信息
  • Android FragmentContainerView如何使用
  • Oracle 字符类型对比
  • Manus AI Agent 技术解读:架构、机制与竞品对比
  • React 中 Hooks 函数及作用
  • 玛卡巴卡的k8s知识点问答(一)