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