C++ 作业 DAY5
作业
代码
Widtget.h
class Widget : public QWidget
{
Q_OBJECT
public:
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); //生成小line
line_attr_temp.line = line; //结构体line成员属性
//置此,line_attr_temp所有属性获取完毕
lines_attr.append(line_attr_temp); //放到容器
start = end; //更新start
update();
}
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)
{
//则删除刚刚 鼠标按下 时记录的start
per_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(); //手动更新,触发绘图
}
}
效果
颜色的随时调整
橡皮擦
撤销上一步
撤销完全