前言
本篇来完成一个最基本的绘图小程序,能绘制普通的矩形、圆形、直线、以及任意绘图,并且弥补基础教学中示例程序中的一些瑕疵与不足。一、程序示例
二、重要步骤
修改画图方式 —— 重构思想
根据上一篇画笔工具的讲解,不论是用多边形边绘图,还是用绘制路径来绘图,程序总是很容易出现以下这种状况:在用鼠标画笔不停画圈时,画的圈数越多,圆圈越是呈现出具有棱角的多边形形态。(此处不贴图了)
有一种解决办法,就是在鼠标绘图时,用image作为绘图设备,然后在重绘函数中只将此image绘制出来,这样就不会因为鼠标点的增多而导致绘图效率降低。
1.拖入控件
拖入一个goupbox与4个radiobutton
并将其四个单选按钮的whatThis属性分别设置为1、2、3、4.
//添加槽函数来判断单选按钮选了谁
private slots:
void checkWho();
增加私有成员,image与num,num用来接收单选按钮的序号,image用于绘图。
private:
Ui::Widget *ui;
QImage image;
int num = 1;//默认为1 代表绘制矩形
2.构造函数初始化变量
代码如下:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
for(QRadioButton *bt:ui->groupBox->findChildren<QRadioButton*>()){
connect(bt,&QRadioButton::clicked,this,&Widget::checkWho);
}//找出所有单选按钮,为它们绑定到checkWho槽函数上
image = QImage(1920,1080,QImage::Format_ARGB32);
image.fill(QColor(255,255,255,0));
}
void Widget::checkWho()
{
//QObject::sender()判断信号的发出者是谁,
//通过获取whatthis设置的文本值,可以判断是哪个单选按钮被选中
this->num = ((QRadioButton*)QObject::sender())->whatsThis().toInt();
}
3.重写事件函数
protected:
bool event(QEvent *event) override;
//当然,还需要一些其他的私有成员
private:
QPoint first,before,last;
QPainter painter; //画家
QPainterPath path; //路径 (只用于基本图形 如矩形、圆形、直线)
重写函数代码如下:
bool Widget::event(QEvent *event)
{
QMouseEvent *e = static_cast<QMouseEvent*>(event);
if(event->type()==QEvent::MouseButtonPress){
first = last = e->pos(); //
this->update();
}
else if(event->type()==QEvent::MouseMove){
before = last; //before与last记录鼠标路径的最后两个点
last = e->pos();
painter.begin(&image); //开始画画
Widget::setPenStyle(); //设置画笔风格
switch (num) { //画什么图
case 1: //矩形
path.clear();
path.addRect(QRect(first,last).normalized());
break;
case 2: //圆形
path.clear();
path.addEllipse(QRect(first,last).normalized());
break;
case 3: //直线
path.clear();
path = QPainterPath(first);
path.lineTo(last);
break;
case 4: //画笔涂鸦
painter.drawLine(before,last);
break;
}
painter.end(); //别忘记结束
update(); //更新界面
}
else if(event->type()==QEvent::MouseButtonRelease){
painter.begin(&image);
Widget::setPenStyle(); //设置画笔样式
painter.drawPath(path); //松开鼠标后,能才确定路径长什么样子
//此时才将路径画在图片上
painter.end();
}
if(event->type()==QEvent::Paint){
painter.begin(this); //屏幕上绘图
Widget::setPenStyle(); //设置画笔样式 (可以试试不设置会是什么样子)
painter.drawImage(0,0,image);//画图片 之前的图形都花在了图片上,此时就画图片即可
if(!path.isEmpty()) //路径未确定时(鼠标未松开时)有值
painter.drawPath(path);//则画出路径的样子
painter.end();
}
return QWidget::event(event);
}
void Widget::setPenStyle()
{
QPen pen(QColor(255,0,0));
pen.setWidth(3);
painter.setPen(pen);
painter.setRenderHint(QPainter::Antialiasing, true);
}
时间不是很够,想十分钟草率搞定这文章算了,于是没太细致的讲解,此程序仍是初学者练习程序,后期定然还要改进,比如橡皮擦等等、路径撤回功能等等。
项目地址
下一篇:QPainter绘图工具的完善