Qt实现2D绘图主要基于QPainter、QPaintDevice、QPaintEngine三个类,- —
绘图由QPainter完成具体的操作,可以绘制一切想要的图形,比如线条、矩形、圆乃至更复杂的图形,还可以绘制文本和图片。
绘图操作一般是在一个部件中的重绘事件的处理函数paintEvent()
中进行绘制。
在paintEvent()
函数中首先要创建QPainter对象,然后使用该对象进行图形的绘制,最后销毁QPainter对象。
具体实现操作如下:
重写绘图事件paintEvent()
;
在绘图事件中声明画家对象QPainter painter(this);
,this表示在当前部件上绘图,如果不指定this,可以使用QPainter::begin(this)和QPainter::end()两个函数,绘制函数在两个函数中间调用,也表示在当前部件上绘制;
使用QPainter::draw*
函数可以绘制线条、矩形、圆、文字等;
使用QPainter::setPen()
可以设置画笔;
使用QPainter::setBrush()
可以设置画刷;还可以使用QGradient
类和QBrush
类一起实现渐变填充,Qt支持的渐变填充有:
QLinearGradient
;QRadialGradient
;ConicalGradient
;线性渐变参考代码:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this); // 在当前widget窗口中绘画,指定绘图设备
// 设置渐变填充
QLinearGradient linearGradient(QPointF(40,190),QPointF(70,190));
// 设置渐变填充的颜色
linearGradient.setColorAt(0,Qt::red);
linearGradient.setColorAt(0.5,Qt::cyan);
linearGradient.setColorAt(1,Qt::green);
// 指定渐变区域以外的区域的扩散方式
linearGradient.setSpread(QGradient::RepeatSpread);
// 设置画刷为渐变类型
painter.setBrush(linearGradient);
painter.drawRect(QRect(QPoint(20,20),QPoint(200,200)));
}
绘制基本图形示例代码:
void Widget::paintEvent(QPaintEvent *event)
{
// 实例化画家类
QPainter painter(this); // 在当前widget窗口中绘画,指定绘图设备
QPen pen(QColor(45,150,56));
pen.setWidth(3); // 设置画笔宽度
pen.setStyle(Qt::DotLine);
painter.setPen(pen); // 设置画笔颜色
// 画刷设置填充色,封闭图形会填充
QBrush brush(Qt::darkGray);
brush.setStyle(Qt::Dense7Pattern);
painter.setBrush(brush);
painter.drawLine(0,0,100,100); // 划线
painter.drawEllipse(QPoint(100,100),50,50);
painter.drawRect(QRect(QPoint(20,20),QPoint(200,200)));
}
QPainter
高级绘图方法:
QPainter::setRenderHint()
可以设置绘制的图形是抗锯齿能力;
QPainter::translate()
移动QPainter
对象;
QPainter::save()
保存QPainter
对象的状态;
QPainter::restore()
还原QPainter
对象的状态
发生重绘的条件:
手动调用绘图事件可以使用**update()
**或repaint()
进行重绘,repaint()
会立即进行重绘操作,参考代码:
// 点击移动按钮,移动图片
connect(ui->pushButton,&QPushButton::clicked,this,[=](){
// 手动调用重绘图形事件,调用update()更新
update();
});
被隐藏的部件被重新调用;
其它一些原因;
QPainter
提供了复合模式来完成数字图像的混合,即如何将源图像的像素和目标图像的像素进行合并,通过调用QPainter::setCompositionMode()
实现,通过传递的函数参数确定不同的混合类型。
绘图设备是指继承QPainterDevice
的子类。Qt提供了这样的类,分别是QPixmap
、QBitmap
、QImage
、QPicture
。
QPixmap
为图像在屏幕上的显示做了优化;QBitmap
是QPixmap
的子类,色深限定为1,可以使用QPixmap::isBitmap()
确定一个QPixmap
对象是不是一个QPixmap
。QImage
为图像的像素级访问做了优化;QPicture
可以记录和重现QPainter
的各条命令;还可以使用
QImageReader
类从文件或其它设备中读取图像,该类提供了一个格式无关的接口,该类依赖于图像底层的支持,类中的一些操作可以节省内存和加快图像的读取;使用QImageWrite
类存储图像。
// Pixmap绘图设备,为平台做显示的优化
QPixmap pixmap(400,300);
// 填充背景色
pixmap.fill(Qt::white);
QPainter painter(&pixmap);
painter.setPen(QPen(Qt::green)); // 设置画笔
painter.drawEllipse(QPoint(100,100),50,50);
// 保存图片
pixmap.save("D:\\pix.png");
// QImage绘图设备,可以对像素进行访问
QImage image(600,400,QImage::Format::Format_RGB32);
image.fill(Qt::white); // 填充背景色
QPainter painter(&image);
painter.setPen(QPen(Qt::blue)); // 设置画笔
painter.drawEllipse(QPoint(100,100),50,50);
可以在painteEvent()
中对像素值进行修改,示例:
void Widget::paintEvent(QPaintEvent *event)
{
// 使用QImage对像素进行修改
QImage image;
image.load(":/images/phone");
QPainter painter(this);
// 修改像素值
for(int i=20;i<100;++i)
{
for(int j=20;j<100;++j)
{
QRgb value = qRgb(0,0,255);
image.setPixel(j,i,value);
}
}
painter.drawImage(10,10,image);
}
记录和重现绘图指令
// QPicture绘图设备,可以记录和重设绘图指令
QPicture pic;
QPainter painter;
painter.begin(&pic); // 开始在pic上绘图
painter.setPen(QPen(Qt::red)); // 设置画笔
painter.drawEllipse(QPoint(200,200),100,100);
painter.end(); // 结束绘图
pic.save("D:\\pic"); // 记录了上面的绘图指令,后缀可以随意,甚至没有后缀
// 重现绘图指令
QPicture pic;
pic.load("D:\\pic");
QPainter painter(this);
painter.drawPicture(0,0,pic);