完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
|
|
相关推荐
1个回答
|
|
概述
QPainter类在窗口和其他绘制设备上执行低级绘制。 QPainter提供高度优化的功能来完成大多数图形用户界面程序所需的工作。它能画出从简单线条到复杂形状如饼图和弦等一切图形。它还可以绘制对齐的文本和像素图。通常,它绘制一个“自然”坐标系,但它也可以进行视图和世界变换。QPainter可以对继承QPaintDevice类的任何对象进行操作。 QPainter的常见用法是在窗口的绘制事件中:构造和自定义(例如设置笔或画笔)绘制器。然后画。记住在绘制后销毁QPainer对象。例如: QPainter的核心功能是绘图,但是类还提供了几个功能,允许您自定义QPainter的设置及其渲染质量,以及其他启用剪辑的功能。此外,还可以通过指定绘制者的合成模式来控制不同形状合并在一起的方式。 函数QPainter::isActive()的作用是:指示绘制程序是否处于活动状态。painter由begin()函数和接受QPaintDevice参数的构造函数激活,end()函数和析构函数将停用它。 与QPaintDevice和QPaintEngine类一起,QPainter构成了qt绘图系统的基础。QPainter是用于执行绘图操作的类。QPaintDevice表示可以使用QPainter绘制的设备。QPaintEngine提供了一个接口,绘图使用它来绘制不同类型的设备。如果绘图处于活动状态,则device()返回及绘图在其上进行绘图的绘图设备,paintEngine()返回绘图当前正在使用的绘图引擎。有关详细信息,请参见绘图系统。 有时,要求在不通用的设备上作画。QPainer支持一个静态函数来执行此操作,setRedirected()。 警告:当paintdevice是一个窗口时,QPainter只能在paintEvent()函数或paintEvent()调用的函数中使用。 设置属性 可以根据自己的喜好自定义多个设置以使QPainer绘制:
可以随时通过调用save()函数来保存QPainer的状态,该函数将所有可用的设置保存在一个内部堆栈上(入栈)。restore()函数的作用是:将它们恢复(出栈)。 绘制 QPainter提供了绘制大多数基本体的函数:drawPoint()、drawPoints()、drawLine()、drawRect()、drawRoundedRect()、drawEllipse()、drawArc()、drawPie()、drawChord()、drawPolyline()、drawPolygon()、drawConverExpolygon()和drawCubicBezier()。drawRects()和drawLines()这两个函数使用当前的画笔在给定的QRects或QLines数组中绘制给定数量的矩形或线条。 QPainer类还提供了fillRect()函数,该函数用给定的QBrush填充给定的QRect,以及擦除给定矩形内区域的eraseRect()函数。 所有这些函数都有整数和浮点版本(推荐使用浮点数版本)。 绘制基础 测试对象为QWidget,重载paintEvent函数绘制,如下图: 文字:drawText void Widget::drawText(QPainter *painter){ painter->save(); painter->drawText(rect(), Qt::AlignCenter, "Hello Qt!!!"); painter->restore();} 点:drawPoint,drawPoints void Widget::drawPoint(QPainter *painter){ painter->save(); painter->drawPoint(10, 10); QPoint point(20, 20); painter->drawPoint(point); QPointF pointF(30, 30); painter->drawPoint(pointF); painter->restore();} void Widget::drawPoints(QPainter *painter){ painter->save(); QPoint point[5]; point[0].setX(10); point[0].setY(10); point[1].setX(20); point[1].setY(20); point[2].setX(30); point[2].setY(30); point[3].setX(40); point[3].setY(40); point[4].setX(50); point[4].setY(50); painter->drawPoints(point, 5); QPolygon polypon; polypon << QPoint(10, 70); polypon << QPoint(20, 70); polypon << QPoint(30, 70); polypon << QPoint(40, 70); polypon << QPoint(50, 70); polypon << QPoint(60, 70); painter->drawPoints(polypon); painter->restore();} 直线:drawLine,drawLines void Widget::drawLine(QPainter *painter){ painter->save(); QLine line(0, 0, 100, 100); painter->drawLine(line); painter->drawLine(0,100, 100, 0); painter->drawLine(QPoint(50, 0), QPoint(50, 100)); painter->restore();} void Widget::drawLines(QPainter *painter){ QVector void Widget::drawPolyline(QPainter *painter){ painter->save(); QPoint point[5]; point[0].setX(10); point[0].setY(10); point[1].setX(20); point[1].setY(10); point[2].setX(40); point[2].setY(40); point[3].setX(40); point[3].setY(60); point[4].setX(50); point[4].setY(50); painter->drawPolyline(point, 5); QPolygon polypon; polypon << QPoint(10, 70); polypon << QPoint(20, 70); polypon << QPoint(30, 70); polypon << QPoint(40, 70); polypon << QPoint(50, 70); polypon << QPoint(60, 90); painter->drawPolyline(polypon); painter->restore();} 多边形:drawPolygon void Widget::drawPolygon(QPainter *painter){ painter->save(); QPoint point[5]; point[0].setX(10); point[0].setY(10); point[1].setX(20); point[1].setY(10); point[2].setX(40); point[2].setY(40); point[3].setX(40); point[3].setY(60); point[4].setX(50); point[4].setY(50); // Qt::OddEvenFill // 指定使用奇数-偶数填充规则填充区域。根据此规则, // 我们使用以下方法确定点是否在形状内。 // 从点到形状外的位置绘制一条水平线,并计算相交的数目。 // 如果交点的数目是奇数,则该点位于形状内部。此模式为默认模式 // Qt::WindingFill // 指定使用非零缠绕规则填充区域。根据此规则, // 我们使用以下方法确定点是否在形状内。 // 从点到形状外部的位置绘制一条水平线。确定每个交叉点的直线方向向上还是向下。 // 绕组数是通过求和每个交叉点的方向来确定的。如果数字不是零,则点在形状内。 // 这种填充模式在大多数情况下也可以被视为闭合形状的交点。 painter->drawPolygon(point, 5, Qt::OddEvenFill);// painter->drawPolygon(point, 5, Qt::WindingFill); painter->restore();} 矩形:drawRect,drawRects void Widget::drawRect(QPainter *painter){ painter->save(); painter->drawRect(10, 10, 40, 40); QRect rect; rect.setX(50); rect.setY(50); rect.setWidth(10); rect.setHeight(10); painter->drawRect(rect); painter->restore();} void Widget::drawRects(QPainter *painter){ painter->save(); QRect rect[2]; rect[0].setX(10); rect[0].setY(10); rect[0].setWidth(10); rect[0].setHeight(10); rect[1].setX(40); rect[1].setY(40); rect[1].setWidth(10); rect[1].setHeight(10); painter->drawRects(rect, 2); painter->restore();} 圆角矩形:drawRoundRect,drawRoundedRect void Widget::drawRoundRect(QPainter *painter){ painter->save(); painter->drawRoundRect(20, 20, 20, 20, 100, 100); // 后两个参数为百分比 painter->drawRoundedRect(50, 50, 20, 20, 10, 5); painter->restore();} 椭圆:drawEllipse void Widget::drawEllipse(QPainter *painter){ painter->save(); painter->drawEllipse(0, 0, 100, 100); painter->drawEllipse(50, 50, 20, 40); painter->restore();} 弧:drawArc void Widget::drawArc(QPainter *painter){ painter->save(); painter->drawArc(0, 0, 100, 100, 0 * 16, 270 * 16); painter->drawArc(20, 20, 60, 60, 270 * 16, 90 * 16); painter->restore();} 弦:drawChord void Widget::drawChord(QPainter *painter){ painter->save(); painter->drawChord(0, 0, 100, 100, 0 * 16, 270 * 16); painter->drawChord(20, 20, 60, 60, 270 * 16, 90 * 16); painter->restore();} 饼图:drawPie void Widget::drawPie(QPainter *painter){ painter->save(); painter->drawPie(0, 0, 100, 100, 0 * 16, 270 * 16); painter->drawPie(20, 20, 60, 60, 270 * 16, 90 * 16); painter->restore();} 路径:drawPath void Widget::drawPath(QPainter *painter){ painter->save(); QPainterPath painterPath; painterPath.addRect(10, 10, 80, 80); painterPath.addEllipse(QRect(20, 20, 60, 60)); painterPath.addRegion(QRegion(30, 30, 40, 40, QRegion::Ellipse)); painter->drawPath(painterPath); painter->restore();} 图片:drawPixmap,drawImage,drawPicture void Widget::drawPixmap(QPainter *painter){ painter->save(); QPixmap pixmap; pixmap.load("D:/1.bmp"); painter->drawPixmap(0, 0, 20, 20, pixmap); QImage image; image.load("D:/1.bmp"); painter->drawImage(30, 30, image); painter->restore();} 绘制像素图和图像 有绘制pixmap/image的函数,即drawPixma()、drawImage()和drawTiledPixmap()。drawPixmap()和drawImage()都会产生相同的结果,只是drawPixmap()在屏幕上更快,而在QPrinter或其他设备上drawImage()可能更快。 有一个drawPicture()函数可以绘制整个QPicture的内容。drawPicture()函数是唯一一个忽略所有绘制设置的函数,因为QPicture有自己的设置。 绘制像素地图和图像的高分辨率版本 高分辨率版本的像素映射的设备像素比值大于1(请参见QImageReader,QPixmap::devicePixelRotio())。如果它与基础QPaintDevice的值匹配,则直接将其绘制到设备上,而不应用其他转换。 例如,在高dpi屏幕上绘制64x64像素大小的QPixmap(设备像素比为2)时,设备像素比也为2。请注意,pixmap在用户空间中有效地为32x32像素。qt中基于pixmap大小计算布局几何图形的代码路径将使用此大小。这样做的效果是,像素地图显示为高dpi像素地图,而不是大像素地图。 渲染质量 要使用QPainter获得最佳渲染结果,应使用平***立的QImage作为绘制设备;即使用QImage将确保结果在任何平台上具有相同的像素表示。 QPainter类还通过其RenderHint枚举和对浮点精度的支持提供了一种控制渲染质量的方法:用于绘制原语的所有函数都具有浮点版本。这些通常与QPainer::Antialiasing渲染结合使用。 抗锯齿是QPainter的渲染默认参数之一。QPainter::RenderHints用于向QPainter指定任何给定引擎可能遵守或不遵守的标志。QPainter::Antialising表示引擎应该尽可能消除原语边缘的混叠,即在原语边缘周围放置额外的像素以平滑边缘。 浮点精度和整数精度之间的差异是一个精度问题,并且在应用程序的主窗口中可见:即使计算圆的几何图形的逻辑是相同的,但浮点确保每个圆之间的空白大小相同,而整数使两个和两个圆成为假装他们属于一起。原因是基于整数的精度依赖于非整数计算的舍入。 RenderHint枚举指定任何给定引擎可能遵守或不遵守的QPainer标志。
坐标变换 通常,QPainter在设备自己的坐标系统(通常是像素)上工作,但QPainter对坐标转换有很好的支持。 最常用的转换是缩放、旋转、平移和剪切。使用scale()函数按给定的偏移量缩放坐标系,使用rotate()函数顺时针旋转坐标系,使用translate()将坐标系平移(即向点添加给定的偏移量)。还可以使用shear()函数围绕原点扭曲坐标系。有关剪切坐标系的可视化,请参见仿射变换示例。 所有变换操作都在转换worldTransform()上操作。矩阵将平面中的一个点转换为另一个点。有关转换矩阵的详细信息,请参见坐标系和QTransform文档。 setWorldTransform()函数的作用是:替换或添加到当前设置的worldTransform()。resetTransform()函数的作用是:重置使用translate()、scale()、shear()、rotate()、setworldTransform()、setviewport()和setwindow()函数进行的任何转换。deviceTransform()返回从逻辑坐标转换为平台相关绘制设备的设备坐标的矩阵。只有在依赖于平台的句柄上使用平台绘制命令时才需要后一个函数,并且平台不会自然地进行转换。 使用QPainer绘制时,我们使用逻辑坐标指定点,然后将逻辑坐标转换为绘制设备的物理坐标。逻辑坐标到物理坐标的映射由QPainer的combinedTransform()、viewport()和window()以及worldTransform()的组合处理。viewport()表示指定任意矩形的物理坐标,window()以逻辑坐标描述相同的矩形,worldTransform()与转换矩阵相同。 剪切 剪切的作用是通过对元素进行剪切来控制元素的可显示区域,也就是在 clip 指定的范围内的内容才能显示出来,正是使用任意形状的 QPainterPath 作为 QPainter的clip,就能绘制出我们想要的效果,例如绘制上图显示的圆形和星形的图片。 QPainer可以将任何绘图操作剪切到矩形、区域或矢量路径。当前剪辑可以使用函数clipRegion()和clipPath())。路径或区域是否首选(更快),取决于基础paintEngine()。例如,QImage绘制引擎偏好路径,而x11绘制引擎偏好区域。设置剪辑是在画图的逻辑坐标中完成的。 QPainter剪切后,绘制设备也可以被剪切。例如,大多数窗口会剪切掉子窗口使用的像素,而大多数打印机会剪切掉靠近纸张边缘的区域。clipRegion()或hasClipping()的返回值不反映此附加剪切。 合成模式 QPainer提供了QPainter::CompositionMode枚举,它定义了数字图像合成的Porter-Duff规则;它描述了一个模型,用于将一个图像中的像素、源、另一个图像中的像素、目标组合在一起。 两种最常见的组合形式是Source和SourceOver。Source用于将不透明对象绘制到绘制设备上。在此模式下,源中的每个像素都将替换目标中的相应像素。在SourceOver合成模式中,源对象是透明的,并绘制在目标的顶部。 请注意,组合转换操作pixelwise。因此,使用图形基元本身和其边界矩形之间存在差异:边界矩形包含alpha==0的像素(即基元周围的像素)。这些像素将覆盖另一个图像的像素,有效地清除这些像素,而Source只覆盖其自身的区域。 性能 QPainter是一个丰富的框架,它允许开发人员进行各种各样的图形操作,如渐变、合成模式和矢量图形。而QPainer可以跨各种不同的硬件和软件堆栈执行此操作。当然,硬件和软件的底层组合对性能有一定的影响,并且由于排列的数量多,确保每个操作与所有组合模式、画笔、剪切、转换等的各种组合结合起来都很快就接近一个不可能完成的任务。作为一个折衷方案,我们选择了QPainer API和后端的一个子集,在这里,性能可以保证在给定的硬件和软件组合下尽可能好地得到它。 作为高性能引擎,我们关注的后端是:
枚举详解 图像混合模式枚举:enum QPainter::CompositionMode 定义数字图像合成支持的模式。合成模式用于指定一个图像(源)中的像素如何与另一个图像(目标)中的像素合并。 请注意,位光栅操作模式(用RasterOp前缀表示)仅在x11和光栅绘制引擎中支持。这意味着在Mac上使用这些模式的唯一方法是通过QImage。笔和画笔(带alpha组件的)不支持RasterOp表示的混合模式。此外,打开QPainer::Antialiasing渲染提示将有效地禁用RasterOp模式。 最常见的类型是SourceOver(通常称为alpha混合,可理解为像素颜色通道),其中源像素在目标像素的顶部混合,这样源的alpha组件定义像素的半透明性。 一些合成模式需要源图像或目标图像中的alpha通道才能产生效果。为了获得最佳性能,最好使用图像格式“format_ARGB8565_Premultiplied”(A-透明,R-红,G-绿,B-蓝,8565依次代表8位、5位、6位、5位)。 当设置合成模式时,它适用于所有绘制操作器、pens、brushes、gradients和pixmap/image。
PixmapFragmentHints类型是QFlags 渲染枚举:enum QPainter::RenderHint、flags QPainter::RenderHints RenderInts用于向QPainer指定任何给定引擎可能遵守或不遵守的标志。
|
||
|
||
只有小组成员才能发言,加入小组>>
4526个成员聚集在这个小组
加入小组3339 浏览 0 评论
航顺(HK)联合电子发烧友推出“近距离体验高性能Cortex-M3,免费申请价值288元评估板
4268 浏览 1 评论
4295 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 21:20 , Processed in 0.587998 second(s), Total 75, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号