作业
代码
Widtget.h
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;/************************ 起始终止坐标 ************************/QPoint end;QPoint start;QVector<QPoint> per_start_list; //容器 记录每一次鼠标按下的start/************************ 画笔相关 ************************/QPainter painter; //绘画QPen pen; //画笔/************************ 移动轨迹line ************************/struct line_attr{QLine line; //线长QColor color = Qt::black; //颜色int width = 1; //粗细}line_attr_temp; //line属性bool rubber_in_use=0; //橡皮擦标志位:0未用 1使用QVector<line_attr> lines_attr; //容器 记录每一个move时 line的属性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();void on_pushButton_3_clicked();void on_pushButton_4_clicked();void on_pushButton_5_clicked();
};
#endif // WIDGET_H
Widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}/**************** 绘画逻辑 ****************/
void Widget::paintEvent(QPaintEvent *event)
{painter.begin(this);for(auto perline:lines_attr){pen.setColor(perline.color);pen.setWidth(perline.width);painter.setPen(pen);painter.drawLine(perline.line);}painter.end();
}/**************** 鼠标逻辑 ****************/
void Widget::mouseMoveEvent(QMouseEvent *event)
{end = event->pos(); //获取鼠标最后位置QLine line(start,end); //生成小lineline_attr_temp.line = line; //结构体line成员属性//置此,line_attr_temp所有属性获取完毕lines_attr.append(line_attr_temp); //放到容器start = end; //更新startupdate();
}void Widget::mousePressEvent(QMouseEvent *event)
{start = event->pos();per_start_list << start;
}void Widget::mouseReleaseEvent(QMouseEvent *event)
{end = event->pos();// 检查:如果鼠标没有移动if(per_start_list.last()==end){//则删除刚刚 鼠标按下 时记录的startper_start_list.removeLast();}
}
/*
错误现象:画线后,空点一次,再使用撤销,会出现段错误
错误原因:空点时,起始坐标start 放入容器中,但是没有产生线段,撤销时的判断 "" 永远无法达到,会一直删除最后一个,直到段错误
错误解决:如果空点,即 "start==end" 则不写入容器
特殊情况?如果没有空点,但是移动后 "start==end" ????
*//**************** 画笔颜色 ****************/
// 打开调色板
void Widget::on_pushButton_clicked()
{line_attr_temp.color = QColorDialog::getColor(Qt::black,this,"选择颜色");
}/**************** 画笔粗细 ****************/
void Widget::on_pushButton_2_clicked()
{line_attr_temp.width=1;
}void Widget::on_pushButton_3_clicked()
{line_attr_temp.width=5;
}void Widget::on_pushButton_4_clicked()
{line_attr_temp.width=10;
}/**************** 橡皮擦逻辑 ****************/
void Widget::on_pushButton_5_clicked()
{//备份当前画笔属性static struct line_attr line_attr_temp_backup = line_attr_temp;//切换橡皮擦状态rubber_in_use=!rubber_in_use;if(rubber_in_use){//更改橡皮擦文本ui->pushButton_5->setText("使用中");//设置橡皮擦画笔line_attr_temp.color = this->palette().color(QPalette::Background);qDebug() << "北京颜色" << this->palette().color(QPalette::Background);line_attr_temp.width = 30;//其他操作ui->pushButton->setEnabled(0); //使调色板失效ui->pushButton_2->setEnabled(0); //使画笔粗细失效ui->pushButton_3->setEnabled(0);ui->pushButton_4->setEnabled(0);}else{//按钮文本描述ui->pushButton_5->setText("Erasers");//恢复画笔属性line_attr_temp=line_attr_temp_backup;//其他操作ui->pushButton->setEnabled(1);ui->pushButton_2->setEnabled(1);ui->pushButton_3->setEnabled(1);ui->pushButton_4->setEnabled(1);}
}/**************** Ctrl + Z ****************/
void Widget::keyPressEvent(QKeyEvent *event)
{if(event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_Z){qDebug() << "Ctrl + Z 按下";// 如果容器不为空if (!per_start_list.isEmpty()){// 则允许遍历撤销while(lines_attr.last().line.p1() != per_start_list.last()){qDebug() << "成功进入p1()";// 则删除最后一个元素lines_attr.removeLast();}lines_attr.removeLast();per_start_list.removeLast();}update(); //手动更新,触发绘图}
}
效果
颜色的随时调整
橡皮擦
撤销上一步
撤销完全