我爱普洱茶 发表于 2025-3-6 21:28:37

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();
}



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 03.05 QT变乱