Qt :绘图总结
目录
绘图基本逻辑:
①确定绘图设备(画布)
②QPainter进行绘制操作
③后续其他操作
绘图设备(画布)分为两大类:
- this(本线程所在的窗口部分)
- QPixmap、QImage、QPicture
绘制前,请先明确要在什么上进行绘制,如果是this,直接指定父对象即可:
QPainter painter(this);
如果是在其他设备(画布)上:
QImage imageblink(400,300,QImage::Format_ARGB32);//画幅大小,透明,比Pixmap多了格式的设置
QPainter painterforimage(&imageblink);
首先,定义画布,设置画布大小和样式,构造函数中有所赘述
绘制完的图片,可以使用多种方式打印,假设目前已经绘制好的
直接绘制在窗口上:
QPainter p(this);//指定对象为窗口
QRectF targetf(0,0,width(),height());//在前界面中显示大小的尺寸,前两个值是图片左上角的初始坐标值,之后是长和宽
QRectF sourcef(0,0,2000,800);//源文件图片需要显示的大小
p.drawImage(targetf,ImageForSave,sourcef);//ImageForSave为已经绘制好的图片
使用QLabel进行加载:
将QImage转换格式后添加到QLabel中,之后,使用QGridlayout进行布局。
QLabel Plabel;
Plabel.setPixmap(QPixmap::fromImage(ImageForSave));//ImageForSave为已经在线程中绘制好的图片
QGridLayout mainLayout = new QGridLayout(this);//将Label放置于界面中的相应位置
mainLayout->addWidget(&Plabel,1,0,5,5,Qt::AlignCenter | Qt::AlignVCenter);
下面分开进行介绍:
QPainter
Qt中的界面绘图操作,需要在绘图事件,paintEvent中进行绘制。
.h文件:
#include<QPainter>//需要头文件
protected:
void paintEvent(QPaintEvent *event);//绘图事件
.CPP文件:
void correction::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);//如果绘图中不使用event,请将其标记为不使用
/.......
......./
}
关于绘图事件,有两种调用事件,或者触发事件的方式:
- 事件内部自动调用:在窗口需要重新绘制的时候,调用paintEvent事件;
- 使用update( );进行调用,只要程序执行到update( ) ;即可调用paintEvent;
第一种完全是交给系统,当你放大缩小窗口,点击窗口摁键的时候,基本都会触发。
第二种是手动触发,程序执行到这一步,必须进行重绘,比如双线程绘图时,绘图结束后需要将新绘制的图片展示在主窗口上,此时,在代码中添加update();执行到update命令时,程序会启动绘图事件。
下面主要来看一下具体绘图操作过程:
①定义Qpainter类的对象:
QPainter painter(this);
Qpainter类对象的构造函数可以传参,参数为QPainterDevice类的指针对象,QPainterDevice表示绘图设备(最后部分有总结)
定义QPainter类的对象,并将窗口设置为绘图设备
(定义所在的cpp继承于QWidget,且包含#include <QWidget>)
QWidget继承于QPaintDevice,所以可以充当绘图设备。
②设置画笔或画刷
完成QPainter类的对象的定义后,需要定义画笔
绘图之前需要定义画笔,即Qpen;
QPen pen;//定义画笔
pen.setColor(QColor(255,26,42));//设置颜色
pen.setStyle(Qt::SolidLine);//设置线性
pen.setWidth(10);//设置线宽
painter.setPen(pen);//将画笔交给画家
除去上面这种方式,还有其他方式:
可以看到Qpen的构造函数是可以传参的,定义的同时进行必要的设置:
painter.setPen(QPen(QColor(0, 160, 230), 6));
//只设定了画笔颜色和画笔的线宽
画刷的定义相对较简单:
// 设置画刷颜色,填充颜色
painter.setBrush(QColor(255, 160, 90));
只需要输入填充的颜色即可
③基本的绘图操作:
设置完画笔之后,可以进行一些基本的绘图操作:
3.1画线:
我们可以看到,QPainter提供了多个类型的画直线的公共接口,可以根据需求选择,先关内容在帮助文档即可查阅
3.2画圆:
画椭圆的公共接口如上:(圆是特殊的椭圆),也可根据需要进行选取及使用
绘图的公共接口很多此处不再列举
3.3绘制背景图片:
屏幕绘制常使用QPixmap
drawPixmap:
QPainter p(this);//指定对象为窗口
p.drawPixmap(0,0,width(),height(),QPixmap("://image/uk.png"));
//起点,为(0,0),终点为窗口的总长和总高,QPixmap为要绘制的内容
3.4绘制logo或者区域内的内容
绘制相关的I/O的内容,QImage
QRectF targetsix(195,445,162.5,91);//在前界面中显示大小的尺寸,前两个值是图片左上角的初始坐标值,之后是长和宽
QRectF sourcesix(0,0,280,500);//源文件图片需要显示的大小
QImage iamgesix(":/image/5.jpg");
p.drawImage(targetsix,iamgesix,sourcesix);//起始坐标,需要置入的照片
关于 drawImage的帮助文档:
以上加载图片的方式都是相对路径,也可以使用绝对路径
QImage iamgefp;
iamgefp.load("C:/Users/Administrator/Desktop/w1.jpg");//打开指定目录的照片
效果展示(绘制屏幕中的部分内容):
示例1:
void Widget::paintEvent(QPaintEvent *event)
{
qDebug()<<"123";
Q_UNUSED(event);
QPainter painter(this);
// 设置画笔颜色、宽度,RGB,画笔的宽度
painter.setPen(QPen(QColor(0, 160, 230), 6));
// 绘制椭圆
//painter.drawEllipse(QPointF(120, 60), 50, 20);
// 设置画刷颜色,填充颜色
//painter.setBrush(QColor(255, 160, 90));
// 绘制圆,坐标,半径
painter.drawEllipse(QPointF(120, 140), 40, 40);
}
效果展示:
示例2:
void Widget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);//创建QPainter对象并指定绘图设备
QPen pen;//定义画笔
pen.setColor(QColor(255,26,42));//设置颜色
pen.setStyle(Qt::SolidLine);//设置线性
pen.setWidth(2);//设置线宽
painter.setPen(pen);//将画笔交给画家
// 设置画刷颜色,填充颜色
painter.setBrush(QColor(255, 160, 90));
// 绘制圆,坐标,半径
painter.drawEllipse(QPointF(120, 140), 40, 40);
}
绘图设备介绍
这是Qt帮助文档对四种绘图设备的解释:
QImage,QPixmap(QBitmap),QPicture;
- QImage:对I/O设计和优化,在线程中绘图,可以对图片进行修改;
- QPixmap:对屏幕进行绘制,和平台有关,不能对图片进行修改;
- QPicture:保存绘图的状态(二进制文件)
三种绘图设备用法非常相似。
补充(QBitmap继承于QPixmap,单色图,占用内存小,对颜色没有要求时可以考虑)
QPixmap
//QPixmap
//指定绘图设备
QPixmap pixmap(400,300);
QPainter painter(&pixmap);//创建QPainter对象并指定绘图设备
painter.drawPixmap(0,0,width(),height(),QPixmap("://image/bk2.jpg"));
//将绘制的内容投影到主窗口
QPainter forthis(this);
forthis.drawPixmap(0,0,width(),height(),pixmap);
以上内容完全可以用绘制背景代替,这么写只是为了展示和QImage的异同之处,下面代码完全可以到达和上面一样的效果
QPainter truepainter(this);
truepainter.drawPixmap(0,0,width(),height(),QPixmap("://image/bk2.jpg"));
效果展示:
QImage
//QImage部分
QImage imageblink(400,300,QImage::Format_ARGB32);//画幅大小,透明,比Pixmap多了格式的设置
QPainter painterforimage(&imageblink);
//painterforimage.drawImage(0,0,QImage("://image/bk2.jpg"));
//或者使用这种形式
QRectF targetf(0,0,width(),height());//在前界面中显示大小的尺寸,前两个值是图片左上角的初始坐标值,之后是长和宽
QRectF sourcef(0,0,2000,800);//源文件图片需要显示的大小
//可以在此处做一些改变,显示原图片的部分,比如目前是2000,800,只显示原图片的左上角2000x800这个部分的内容
painterforimage.drawImage(targetf,QImage("://image/bk2.jpg"),sourcef);//查看原函数可以发现,这个部分和drawPixmap是有区别的
//QImage部分
//将其绘制到主窗口
QPainter forthis(this);
forthis.drawImage(targetf,QImage("://image/bk2.jpg"),sourcef);//查看原函数可以发现,这个部分和drawPixmap是有区别的
//实际中远不用这么复杂,Qimage部分可以放置于线程之中,通过信号和槽传参,将图片传给主线程,主线程通过上面的方式进行打印即可
效果展示:
QPicture
QPicture picture;
QPainter p;
p.begin(&picture);
p.drawPixmap(0,0,width(),height(),QPixmap("://image/ubk.png"));
p.end();
picture.save("C:/Users/Administrator/Desktop/0502.jpg");
//如果要使用save功能,最后使用QPainter的begin和end功能
保存的图片无法打开,实属正常,因为Picture保存为了二进制模式。
QPixmap和QImage之间的相互转换:
QPixmap转成QImage:
QPixmap pixmap;
pixmap.load("://image/bk2.jpg");
QImage tempimage = pixmap.toImage();
QImage转成QPixmap:
QImage tempimage;
tempimage.load("://image/bk2.jpg");
QPixmap pixmap = QPixmap::fromImage(tempimage);
就目前来看,对背景图片的绘制,使用PIxmap
线程绘图,使用Image,绘制完成后,通过信号和槽传参给主线程,调用update();手动调用PaintEvent,在绘图事件中间线程画好的image打印到主屏幕上。
关于QImage的保存
接口原型:
bool QImage::save(const QString &fileName, const char *format = Q_NULLPTR, int quality = -1) const
.h
QImage ImageForSave;
.cpp
void Widget::getimag(QImage temp)
{
qDebug()<<"get image";
ImageForSave = temp;
Plabel.setPixmap(QPixmap::fromImage(ImageForSave));
update();
QSettings savesetting("./Setting.ini", QSettings::IniFormat);//为了能记住上次打开的路径,这个句子是关键
QString savePath = savesetting.value("LastFilePath").toString();
QString filename1 = QFileDialog::getSaveFileName(this,tr("Save Image"),savePath,tr("Images (*.png)")); //选择路径
bool Flga = ImageForSave.save(filename1);//保存图片
if(Flga == true)
{
QMessageBox::about(this,"提示","保存成功!");
}
else
{
QMessageBox::about(this,"提示","发生错误");
}
}
QImage自带保存接口,输入参数:要将图片保存的路径