实现一个绘图工具,具备以下功能:
-
鼠标绘制线条。
-
实时调整线条颜色和粗细。
-
橡皮擦功能,覆盖绘制内容。
-
撤销功能,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_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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(); // 1mmvoid on_pushButton_3_clicked(); // 5mmvoid on_pushButton_4_clicked(); // 10mmvoid on_pushButton_6_clicked(); // 20mmvoid 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();
}