2025年Qpainter drawtext 与其他重叠(qpainter局部重绘)

Qpainter drawtext 与其他重叠(qpainter局部重绘)本篇读书笔记主要记录 QPainter 的复合模式 amp amp 双缓冲绘图 amp amp 绘图中的其他问题 nbsp 大纲 nbsp nbsp 复合模式 nbsp nbsp 双缓冲绘图 nbsp nbsp 绘图中的其他问题 nbsp nbsp nbsp nbsp 重绘事件 nbsp nbsp nbsp nbsp 剪切 nbsp nbsp nbsp nbsp 读入和写入图像 nbsp nbsp



本篇读书笔记主要记录QPainter的复合模式&&双缓冲绘图&&绘图中的其他问题
大纲:
复合模式
双缓冲绘图
绘图中的其他问题
重绘事件
剪切
读入和写入图像
播放GIF
渲染SVG
复合模式
QPainter提供了复合模式(Composition Modes)来定义如何完成数字图像的复合,即如何将源图像的像素和目标图像的像素进行合并。QPainter 提供的常用复合模式及其效果如下面截图所示,所有的复合模式可以在QPainter的帮助文档中进行查看。
最普通的类型是SourceOver(不设置的话默认是这个)(通常被称为alpha混合),就是正在绘制的源像素混合在已经绘制的目标像素上,源像素的alpha分量定义了它的透明度,这样源图像就会以透明效果在目标图像上进行显示。
若绘图设备是QImage,图像的格式一定要指定为QImage::Format_ARGB32_Premultiplied或者Format_ARGB32,不然复合模式就不会产生任何效果。
当设置了复合模式,它就会应用到所有的绘图操作中,如画笔、画刷、渐变和pixmap/image绘制等。
演示书上的代码:

效果图:
双缓冲绘图
所谓双缓冲(double-buffers)绘图,就是在进行绘制时,先将所有内容都绘制到一个绘图设备(如QPixmap)上,然后再将整个图像绘制到部件上显示出来。
使用双缓冲绘图可以避免显示时的闪烁现象。
从Qt4.0开始,QWidget部件的所有绘制都自动使用了双缓冲,所以一般没有必要在paintEvent()函数中使用双缓冲代码来避免闪烁。
虽然在一般的绘图中无须手动使用双缓冲绘图,不过要想实现一些绘图效果,还是要借助于双缓冲的概念。
下面的程序实现使用鼠标在界面上绘制一个任意大小的矩形的功能。
这里需要两张画布,它们都是QPixmap实例。
其中一个tempPix用来作为临时缓冲区,当鼠标正在拖动矩形进行绘制时,将内容先绘制到tempPix上,然后将tempPix绘制到界面上;
而另一个pix作为缓冲区,用来保存已经完成的绘制。当松开鼠标完成矩形的绘制后,则将tempPix的内容复制到pix上。
为了绘制时不显示拖影,在移动鼠标过程中,每绘制一次都要在刚开始绘制这个矩形的图像上进行绘制,所以需要在每次绘制tempPix之前,先将pix的内容复制到tempPix上。

这里先在临时缓冲区中进行绘图,然后将其绘制到界面上。最后判断是否已经完成了绘制,如果是,则将临时缓冲区中的内容复制到缓冲区中,这样就完成了整个矩形的绘制。这个例子中的关键是pix和tempPix的相互复制,如果想将这个程序进行扩展,可以查看一下网站上的涂鸦板序。
与这个例子很相似的一个应用是橡皮筋线,就是我们在Windows桌面上拖动鼠标出现的橡皮筋选择框。Qt中提供了QRubberBand 类来实现橡皮筋线,使用它只需要在几个鼠标事件处理函数中进行设置即可,具体应用可以查看该类的帮助文档。
绘图中的其他问题
重绘事件 paintEvent(QPaintEvent *event)override; protected
前面讲到的所有绘制操作都是在重绘事件处理函数paintEvent()中完成的,它是QWidget类中定义的函数。也就意味着QtWidgets都是绘图设备
一个重绘事件用来重绘一个部件的全部或者部分区域,下面几个原因中的任意一个都会发生重绘事件:
  • repaint()函数或者update()函数被调用;
  • 被隐藏的部件现在被重新显示;
  • other
大部分部件可以简单地重绘它们的全部界面,但是一些绘制比较慢的部件需要进行优化而只绘制需要的区域(可以使用QPaintEvent::region()来获取该区域),这种速度上的优化不会影响结果。
Qt也会通过合并多个重绘事件为一个事件来加快绘制,当update()函数被调用多次,或者窗口系统发送了多个重绘事件时,那么Qt就会合并这些事件成为一个事件,而这个事件拥有最大的需要重绘的区域。
update()函数不会立即进行重绘,要等到Qt返回主事件循环后才会进行,所以多次调用update()函数一般只会引起一次paintEvent()函数调用。
但是调用repaint()函数会立即调用paintEvent()函数来重绘部件,只有在必须立即进行重绘操作的情况下(比如在动画中),才使用repaint()函数。
update()允许Qt优化速度和减少闪烁,但是repaint()函数不支持这样的优化,所以建议一般情况下尽可能使用update()函数。
还要说明一下,在程序开始运行时就会自动发送重绘事件而调用paintEvent()函数。另外,不要在paintEvent()函数中调用update( )或者repaint()函数。
当重绘事件发生时,要更新的区域一般会被擦除,然后在部件的背景上进行绘制。
部件的背景一般可以使用setBackgroundRole( )来指定,然后使用setAutoFillBackground(true)来启用指定的颜色。
例如,使界面显示比较深的颜色,则可以在部件的构造函数中添加如下代码:
setBackgroundRole(QPalette::Dark);
setAutoFillBackgroud(true);
剪切
QPainter可以剪切任何的绘制操作,它可以剪切一个矩形、一个区域或者一个路径中的内容,
这分别可以使用setClipRect()、setClipRegion()和setClipPath()函数来实现。
剪切会在QPainter的逻辑坐标系统中进行。下面的代码实现了剪切一个矩形中的文字:
读入和写入图像
要读取图像,最普通的方法是使用QImage或者QPixmap的构造函数,或者调用Qlmage: :load()和QPixmap::load()函数。
Qt中还有一个QImageReader类,该类提供了一个格式无关的接口,可以从文件或者其他设备中读取图像。
QImageReader 类可以在读取图像时提供更多的控制,例如,可以使用setScaledSize()函数将图像以指定的大小进行读取,还可以使用setClipRect()读取图像的一个区域。
由于依赖于图像格式底层的支持,QImageReader的这些操作可以节省内存和加快图像的读取
另外,Qt还提供了QImageWriter类来存储图像,它支持设置图像格式的特定选项,比如伽玛等级、压缩等级和品质等。
当然,如果不需要设置这些选项,那么可以直接使用Qlmage: :save()和QPixmap::save( )函数。
播放GIF
QMovie类是使用QImageReader来播放动画的便捷类,使用它可以播放不带声音的简单的动画,比如gif文件格式。
这个类提供了很方便的函数来进行动画的开始、暂停和停止等操作。
渲染SVG
可缩放矢量图形( Scalable Vector Graphics,SVG)是一个使用XML来描述二维图形和图形应用程序的语言。
在Qt中可以使用QSvgWidget类加载一个SVG文件,而使用QSvgRenderer类在QSvgWidget中进行SVG文件的渲染。
这两个类的使用很简单,可以参考SVG Generator Example和SVG Viewer Example示例程序。
Qt参考示例和文档
文档:
示例:Image Composition Example , Composition Modes
本篇源代码
https://github.com/tudouloveloli/QtExampleCode
编程小号
上一篇 2025-03-02 21:21
下一篇 2025-08-09 23:51

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/49261.html