摘要
最近碰到了一个需要在qt中完成二维图像变换的作业,想到刚接触qt时学过qpainter来进行绘画操作,立马就着手码起来;作为一个小白,马上就发现了相应的问题:由于qt内部机制,绘画事件(paintEvent)仅允许在绘画事件下进行(比如我想在某个按钮槽函数下绘画是错误的。查阅了论坛上大部分文章发现很少涉及这样的操作,并且涉及到的操作对于我这种小白来说也是比较难的。
在一晚上的思考下,突然想起可以通过枚举来解决这问题,下面要介绍的就是通过枚举来实现自定义操作“画家的笔”。
代码
widget.h
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void paintEvent(QPaintEvent *event);
signals:
void senddata();
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui;
};
头文件声明绘图事件,之后再重写
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
#include<QMessageBox>
double X1,Y1,X2,Y2,X3,Y3;
enum func
{
ok,
pingyi1,
pingyi2,
pingyi3,
pingyi4,
xuanzhuan,
duicheng,
fangsuo,
}func1;
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("图形变换");
resize(800,600);
//确定
connect(ui->pushButton,&QPushButton::clicked,this,[=](){
X1=ui->lineEdit->text().toDouble();
Y1=ui->lineEdit_2->text().toDouble();
X2=ui->lineEdit_3->text().toDouble();
Y2=ui->lineEdit_4->text().toDouble();
X3=ui->lineEdit_5->text().toDouble();
Y3=ui->lineEdit_6->text().toDouble();
if(ui->lineEdit->text().isEmpty()||ui->lineEdit_2->text().isEmpty()||ui->lineEdit_3->text().isEmpty()||ui->lineEdit_4->text().isEmpty()||
ui->lineEdit_5->text().isEmpty()||ui->lineEdit_6->text().isEmpty())
{
QMessageBox::warning(this,"注意!","请输入正确的数据");
}
else
{
func1 = ok;
update();
}
});
//上移
connect(ui->pushButton_2,&QPushButton::clicked,this,[=](){
func1=pingyi1;
Y1=Y1+20;
Y2=Y2+20;
Y3=Y3+20;
update();
});
//下移
connect(ui->pushButton_6,&QPushButton::clicked,this,[=](){
func1=pingyi2;
Y1=Y1-20;
Y2=Y2-20;
Y3=Y3-20;
update();
});
//左移
connect(ui->pushButton_7,&QPushButton::clicked,this,[=](){
func1=pingyi3;
X1=X1-20;
X2=X2-20;
X3=X3-20;
update();
});
//右移
connect(ui->pushButton_8,&QPushButton::clicked,this,[=](){
func1=pingyi4;
X1=X1+20;
X2=X2+20;
X3=X3+20;
update();
});
//旋转
connect(ui->pushButton_3,&QPushButton::clicked,this,[=](){
func1=xuanzhuan;
double temp1,temp2,temp3;
temp1=X1*cos(0.523)-Y1*sin(0.523);
Y1=X1*sin(0.523)+Y1*cos(0.523);
X1=temp1;
temp2=X2*cos(0.523)-Y2*sin(0.523);
Y2=X2*sin(0.523)+Y2*cos(0.523);
X2=temp2;
temp3=X3*cos(0.523)-Y3*sin(0.523);
Y3=X3*sin(0.523)+Y3*cos(0.523);
X3=temp3;
update();
});
//放缩
connect(ui->pushButton_4,&QPushButton::clicked,this,[=](){
func1=fangsuo;
X1=X1*0.75;
Y1=Y1*0.75;
X2=X2*0.75;
Y2=Y2*0.75;
X3=X3*0.75;
Y3=Y3*0.75;
update();
});
//对称
connect(ui->pushButton_5,&QPushButton::clicked,this,[=](){
func1=duicheng;
Y1=-Y1;
Y2=-Y2;
Y3=-Y3;
update();
});
}
void Widget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
// 反走样
painter.setRenderHint(QPainter::Antialiasing, true);
// 设置画笔颜色
painter.setPen(QColor(0, 160, 230));
//绘制绘图框
painter.drawRect(QRect(QPoint(0,0),QPoint(height(),width()-100)));
// 绘制直线
painter.setPen(QColor(0, 0, 0));
painter.drawLine(QLine(QPoint(height()/2,0),QPoint(height()/2,width()-100)));
painter.drawLine(QLine(QPoint(0,(width()-100)/2),QPoint(height(),(width()-100)/2)));
painter.translate(height()/2,(width()-100)/2);//重新设置坐标轴原点
painter.scale(1,-1);//反转Y轴
switch (func1) {
case ok:
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
break;
case pingyi1:
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
break;
case pingyi2:
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
break;
case pingyi3:
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
break;
case pingyi4:
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
break;
case xuanzhuan:
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
break;
case fangsuo:
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
break;
case duicheng:
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
break;
default:
break;
}
}
Widget::~Widget()
{
delete ui;
}
基本机制就是首先在绘图事件绘制基本的图形框,然后根据不同的图形变换功能func创建相应的枚举值,在connect的槽函数的lambda函数中给func赋值,再通过update函数刷新绘图事件,再在绘图事件函数下,判断func1的值是多少,进而完成相应的功能。
ui界面
ui界面如下,一切从简(为了完成作业
本人代码能力有限,刚学习不久,大佬可能有更好的方法欢迎指正;本文希望可以给和我一样的新人提供帮助。