一、QT绘图原理

Qt4中的2D绘图系统称为Arthur绘图系统,可以使用相同的API在屏幕上和绘图设备上进行绘制,主要基于QPainter、QPainterDevice和 QPainterEngine。QPainter执行绘图操作,QPainterDevice提供绘图设备,是一个二维空间的抽象,QPainterEngine提供一些接口。QPainter用来执行具体的绘图相关操作,如画点,画线,填充,变换,alpha通道等。QPaintDevice类是能够进行绘图的对象的基类,QWidget,QPixmap,QPicture,QImage,以及QPrinter类继承了QPaintEngine类的绘图能力,QPainter类可以在一切继承QPainterDevice的子类上进行绘制操作。

QT中Arthur绘图框架中的基本绘图元素是画笔,画刷。

QPainter类具有GUI程序需要的绝大多数函数,能够绘制基本图形(点,线,矩形,多边形等)以及复杂的图形(如绘图路径)。使用绘图路径(QPaintPath)的优点是复杂形状的图形只用生成一次,再使用的时候只需要调用QPainter::drawPath()就可以绘制。QPainterPath对象可以用来填充,绘制轮廓。

线和轮廓都可以用画笔(QPen)进行绘制,画刷(QBrush)进行填充。画笔定义风格(线形),宽度,笔尖画刷以及端点是如何绘制的(cap-style),端点的连接方式(join-style)。画刷用来填充画笔绘制的图形,可以定制不同的填充模式和颜色的画刷。

当绘制文字时,字体使用QFont类定义,Qt使用指定字体的属性,如果没有匹配的字体,Qt将使用最接近的字体。字体属性可以通过QFontInfo来获取。字体的度量(measurement)使用QFontMetrics类来获取。QFontDatabase类可以获得底层窗口系统所有可用的字体。

通常情况下QPainter以默认的坐标系统进行绘制,也可以用QMatrix类对坐标进行变换。

当绘制时,可以使用QPainter::SetRenderHint函数设置绘图引擎是否启用反锯齿功能使图变得平滑。

QPainter::Antialiasing尽可能进行边的反锯齿绘制

QPainter::TextAntialiasing 尽可能进行文字的反锯齿绘制

QPainter::SmoothPixmapTransform 使用平滑的pixmap变换算法(双线性插值算法),而不是近邻插值算法

1、重写重绘事件处理函数实现绘图

重绘事件处理函数:

void QWidget::paintEvent ( QPaintEvent * event )

基础部件类Qwidget提供的paintEvent函数,是纯虚函数;Qwidget的子类要使用paintEvent函数必须重新实现。在三种情况会发生重绘事件调用paintEvent函数:

A、当窗口部件第一次显示时,系统会自动产生一个绘图事件

B、repaint()与update()函数被调用时

C、当窗口部件被其他部件遮挡,然后又再次显示出来时,就会对隐藏的区域产生一个重绘事件

D、重新调整窗口大小时

2、通过事件过滤器实现重绘

二、绘图工具

绘图时需要先定义一个QPainter类对象,绘图工具可以使Qpen(画笔)和QBrush(画刷)。Qpen(画笔)来绘制轮廓线,QBrush(画刷)用来填充,使用QPen写文本时还可以指定字体(QFont类)。

1、QPen画笔

画笔的属性包括线型,线宽,颜色等。

A、QPen主要成员函数如下:

QPen(Qt::PenStyle style)

QPen(const QColor & color)

QPen(const QBrush & brush, qreal width, Qt::PenStyle style = Qt::SolidLine, Qt::PenCapStyle cap = Qt::SquareCap, Qt::PenJoinStyle join = Qt::BevelJoin)

QPen(const QPen & pen)

void setBrush(const QBrush & brush)

void setCapStyle (Qt::PenCapStyle style)

void setColor (const QColor & color)

void setJoinStyle (Qt::PenJoinStyle style)

void setWidth (int width)

画笔的属性可以在构造函数中指定,也可以使用setStyle(),setWidth(),setBrush(),setCapStyle(),setJoinStyle()等函数设定画笔的各项属性。Qt中使用Qt::PenStyle定义了6种画笔风格,分别是Qt::SolidLine,Qt::DashLine,Qt::DotLine,Qt::DashDotLine,Qt::DashDotDotLine,Qt::CustomDashLine。自定义线风格(Qt::CustomDashLine),需要使用QPen的setDashPattern()函数来设定自定义风格。

画笔的设置代码如下:

QPainter painter(this);

QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);

painter.setPen(pen);

等价于如下代码:

QPainter painter(this);

QPen pen; // creates a default pen

pen.setStyle(Qt::DashDotLine);

pen.setWidth(3);

pen.setBrush(Qt::green);

pen.setCapStyle(Qt::RoundCap);

pen.setJoinStyle(Qt::RoundJoin);

painter.setPen(pen);

B、画笔风格

画笔风格使用Qt::PenStyle枚举定义。

C、画笔的端点风格( Qt::PenCapStyle)

画笔端点风格决定了线的端点样式,只对线宽大于1的线有效。Qt使用枚举定义了三种端点风格,分别为Qt::SqureCap,QT::FlatCap,Qt::RoundCap。

D、画笔连接风格(Qt::PenJoinStyle)

画笔连接风格是两条线如何连接,连接风格对线宽大于等于1的线有效。Qt使用枚举定义了四种连接类型,分别是Qt::MiterJoin,Qt::BevelJoin,Qt::RoundJoin,Qt::SvgMiterJoin。

2、QBrush画刷

在Qt中图形使用QBrush进行填充,画刷包括填充颜色和填充模式(风格)。

A、QBrush主要成员函数

QBrush(Qt::BrushStyle style)

QBrush(const QColor& color,Qt::BrushStyle style = Qt::SolidPattern)

QBrush(Qt::GlobalColor color,Qt::BrushStyle style = Qt::SolidPattern)

QBrush(const QColor & color, const QPixmap & pixmap)

QBrush(Qt::GlobalColor color, const QPixmap & pixmap)

QBrush(const QPixmap & pixmap)

QBrush(const QImage & image)

QBrush(const QBrush & other)

QBrush(const QGradient & gradient)

const QColor &color() const

const QGradient *gradient() const

const QMatrix &matrix() const

void setColor(const QColor & color)

void setColor(Qt::GlobalColor color)

void setMatrix(const QMatrix & matrix)

void setStyle(Qt::BrushStyle style)

void setTexture(const QPixmap & pixmap)

void setTextureImage(const QImage & image)

void setTransform(const QTransform & matrix)

Qt::BrushStyle style() const

QPixmap texture() const

QImage textureImage() const

QTransform transform() const

B、填充颜色

在Qt中,颜色使用QColor类表示,QColor支持RGB,HSV,CMYK颜色模型。QColor还支持alpha混合的轮廓和填充。RGB是面向硬件的模型,颜色由红绿蓝三种基色混合而成;HSV模型比较符合人对颜色的感觉,由色调(0-359),饱和度(0-255),亮度(0-255)组成;CMYK由青,洋红,黄,黑四种基色组成,主要用于打印机等硬件拷贝设备上,每个颜色分量的取值是0-255。

C、填充模式

填充模式通过枚举类型Qt::BrushStyle来实现,默认值是Qt::NoBrush,不进行任何填充;填充模式包括基本填充模式,渐变填充,和纹理填充模式。不同的填充模式显示效果如下:

Qt4中,QBrush提供了三种渐变填充:线性(QLinearGradient),圆形(QRadialGradient)和圆锥渐变(QConicalGradient),所有的类都从QGradient类继承。

线性渐变填充

线性渐变填充指定两个控制点,画刷在两个控制点之间进行颜色插值。通过创建QLinearGradient对象来设置画刷。

QLinearGradient linearGradient(0,0,200,100);

linearGradient.setColorAt(0,Qt::red);

linearGradient.setColorAt(0.5,Qt::green);

linearGradient.setColorAt(1,Qt::blue);

painter.setBrush(linearGradient);

painter.drawRect(0,0,200,100);

在QGradient构造函数中指定线行填充的两点分别为(0,0),(100,100)。 setColorAt()函数在0-1之间设置指定位置的颜色。

圆形渐变填充

圆形渐变填充需要指定圆心,半径和焦点。画刷在焦点和圆上的所有点之间进行颜色插值,通过创建QRadialGradient对象设置画刷。

QRadialGradient radialGradient(50,50,50,30,30);

radialGradient.setColorAt(0.2,Qt::cyan);

radialGradient.setColorAt(0.8,Qt::yellow);

radialGradient.setColorAt(1,Qt::magenta);

painter.setBrush(radialGradient);

painter.drawEllipse(0,0,100,100);

圆锥渐变填充

圆锥渐变填充指定圆心和开始角,画刷沿圆心逆时针对颜色进行插值,通过创建QConicalGradient对象并设置画刷。

QConicalGradient conicalGradient(60,40,30);

conicalGradient.setColorAt(0,Qt::gray);

conicalGradient.setColorAt(0.4,Qt::darkGreen);

conicalGradient.setColorAt(0.6,Qt::darkMagenta);

conicalGradient.setColorAt(1,Qt::drakBlue);

painter.setBrush(conicalGradient);

painter.drawEllipse(0,0,100,100);

其他填充模式

其他填充模式通过setStyle(Qt::BrushStyle style)函数进行设置。

如果实现自定义填充,可以使用QPixmap或者QImage对象进行纹理填充。两种图像分别使用setTexture()和setTextureImage()函数加载纹理。

D、alpha通道

在windows,Mac OSX和有XRender扩展的X11系统上,Qt4能够支持Alpha通道,通过使用Alpha通道,可以实现半透明效果,QColor类中定义了Alpha通道的透明度,0表示完全透明,255表示完全不透明。QWidget类有一个属性windowOpacity,通过setWindowOpacity(qreal level)可以设置窗口的透明度。但该属性和Alpha通道的原理并不相同,Qt4在Windows和Mac OS X平台上才支持该属性,但在X11平台上却需要Composite扩展才能工作。(alpha通道使用的是X11的xRender扩展)。

3、双缓冲绘图

在Qt4中,所有的窗口部件默认都使用双缓冲进行绘图。使用双缓冲,可以减轻绘制的闪烁感。在有些情况下,用户要关闭双缓冲,自己管理绘图。下面的语句设置了窗口部件的Qt::WA_PaintOnScreen属性 ,就关闭了窗口部件的双缓冲。

widget->setAttribute(Qt::WA_PaintOnScreen);

Qt4不再提供异或笔,组合模式QPainter::CompostionMode_Xor()并不是异或笔,Qt4只提供了QRubberBand实现矩形和直线的绘图反馈。要实现在绘图中动态反馈必须使用其他方法。程序中使用双缓冲来解决这个问题。在绘图过程中,一个缓冲区绘制临时内存,一个缓冲区保存绘制好的内容,最后进行合并。

在交互绘图过程中,程序将图像缓冲区复制到临时缓冲区,并在临时缓冲区上绘制,绘制完毕在将结果复制到图像缓冲区,如果没有交互复制,则直接将图像缓冲区绘制显示到屏幕上。

4、绘图路径

绘图路径(painter path)由基本图元(矩形,椭圆,直线,曲线)组成,绘图路径可以是闭合的路径,如矩形和圆,或者是非闭合的路径,如直线和曲线。绘图路径在Qt中使用QPainterPth类表示,提供了绘图操作的容器,可以使图形能够复用。绘图路径可以进行填充,显示轮廓和裁剪。要生成可填充的轮廓的绘图路径,可以使用QPainterPathStroker类。使用QPainterPath的优点是复杂的图形只需创建一次,就可以多次使用。QPainterPath对象可以是只有起点的空路径,或者从其他QPainterPath对象复制,创建了QPainterPath对象后,可以使用lineTo(),cubicTo(),quadTo() 函数将直线和曲线添加到路径中来,直线和曲线从currentPosition()开始绘制。currentPosition()总是返回最后的子路经绘制的终点。使用moveTo()函数可以在不增加路径的情况下移动currentPositon(),它关闭了一个子路经,开始一个新的子路经。 closeSubPath()也可以关闭当前路径,并从currentPosition()连接一条直线到绘图路径的起点。QPainter可以使用 addEllipse(),addPath(),addRect(),addRegion(),

addText()将Qt的一些基本图元加入绘图路径。一个已有的绘图路径可以通过connectPath()函数加入到另一个绘图路径中。

箭头的绘制代码如下:

QPainterPath path;

path.moveTo(10,100);

path.cubicTo(10,100,100,10,200,70);

path.lineTo(200,50);

path.lineTo(220,80);

path.lineTo(200,110);

path.lineTo(200,90);

path.cubicTo(200,100,100,50,50,100);

QPainter painter(this);

QPen pen(QColor(255,0,0),2);

painter.setPen(pen);

painter.drawPath(path);

Qt提供了两种填充方式,Qt::OddEventFill和Qt::WindingFill。Qt::OddEvent是默认的填充规则,指定QPainterPath使用奇偶填充规则,奇偶填充规则判断一个点是否在路径图形内的方法是从该点画一条水平线到路径外,计算水平线和路径的交点数,如果交点是奇数个则说明该点在路径图形内。QPainterPath还有一些函数可以获取路径信息,如elementAt()函数可以取出指定的子路经元素,isEmpty()函数判断当前路径是否为空。controlPointRect()函数返回路径中所有的点和控制点的矩形,controlPointRect函数运行速度比返回精确包容框boundingRect()函数快得多。contains()函数判断一个点或一个矩形是否在路径内。intersects()判断指定的矩形与路径是否相交。QPainterPath可以将矩形图形转换为其他图形,如使用toFillPolygon(),toFillPolygon(),toSubpathPOlygons()函数将路径转化为多边形。

QPainterPath还可以使用文字作为路径。

使用线性渐变填充的文字路径实现代码:

QPainter painter(this);

QLinearGradient linearGrad(QPointF(200,0),QPointF(1000,0));

linearGrad.setColorAt(0,Qt::black);

linearGrad.setColorAt(1,Qt::white);

QFont font("隶书

c++ qt获取电脑的内存_QT开发(十四)——QT绘图系统相关推荐

  1. c++ qt获取电脑的内存_Qt官方示例-TCP客户端/服务器示例

    该示例演示了在本地主机上的TCP客户端和服务器是如何通讯的. 客户端 绑定信号槽. connect(&tcpClient, &QAbstractSocket::connected, t ...

  2. c++ qt获取电脑的内存_Qt官方示例信号量

    ❝ 演示Qt多线程的信号量操作编程. ❞   生产者将数据写入缓冲区,直到到达缓冲区末尾为止,然后从头开始重新开始,覆盖现有数据.使用者线程读取生成的数据,并将其写入标准错误.   信号量比互斥量可以 ...

  3. 使用python获取CPU和内存信息的思路与实现(linux系统)

    From: http://blog.csdn.net/preterhuman_peak/article/details/40649229 linux里一切皆为文件,在linux/unix的根目录下,有 ...

  4. qt获取窗口的右上角位置_智能座舱QT应用实例 -- Mode/View

    开门见山,The model/view architecture 是Qt用来分离数据和UI的一种设计方式,也就是设计模式中的Model-View-Controller (MVC). view 和 mo ...

  5. i.MX 6ULL 驱动开发 十四:LED(paltform驱动框架)

    一.驱动设计思想(机制.策略.分离.分层) 驱动设计思想(机制.策略.分离.分层)_正在起飞的蜗牛的博客-CSDN博客_机制与策略分离 二.驱动开发框架 三.platform 基本概念 Linux 驱 ...

  6. 【Android游戏开发十四】深入Animation,在SurfaceView中照样使用Android—Tween Animation!

     李华明Himi 原创,转载务必在明显处注明: 转载自 [黑米GameDev街区] 原文链接:  http://www.himigame.com/android-game/331.html 很多童鞋说 ...

  7. safari video一次性获取一个文件_Requests库(十四)一文揭秘如何获取快手关注的视频...

    由于微信公众号推送改为了信息流的形式,防止走丢,请给加个星标 ⭐,你就可以第一时间接收到本公众号的推送! Requests库分享系列: Requests库(一) Requests库(二) Reques ...

  8. SQL2K数据库开发十四之表操作设置用户对表的权限

    1.在企业管理器中双击Products表,打开表的属性窗口,如下图: 2.点击"权限"按钮可以设置用户或数据库角色对该表所拥有的各种操作的权限.如下图: 3.点击"列&q ...

  9. qt获取combobox的值_Qt官方示例嵌套甜甜圈

    ❝ 本示例演示如何使用QPieSeries API创建嵌套的甜甜圈图. ❞ 创建嵌套甜甜圈图   先创建一个QChartView实例并启用抗锯齿.然后从QChartView实例获得一个QChart对象 ...

最新文章

  1. groupby python_【实战案例】用Python做出5 种非传统的可视化技术,超炫酷的动态图...
  2. 推荐一些C++经典书籍
  3. Android版俄罗斯方块的实现
  4. html5赛车小游戏,html5公路赛车小游戏
  5. asp.net控件开发基础(21)
  6. 【论文解读】CVPR 2021 当之无愧的最佳论文奖:GIRAFFE,一种可控图像合成方法...
  7. 循环队列-队列的顺序表示和实现
  8. Centos 开机后,登录时无法输入密码怎么解决
  9. SAP UI5 应用开发教程之三十三 - SAP UI5 应用的响应式布局特性(Responsiveness)试读版
  10. 下一代微服务架构基础:ServiceMesh?
  11. void符合c语言用户标识吗,1以下可用作C语言用户标识符的是()。void,define,.doc...
  12. nolo手柄配对不上_nolo手柄连接不上
  13. milk and news paper(transfer)
  14. 辞职腾讯去了小公司,从0到1搭建后端架构,工资就翻倍了
  15. 安卓平台有哪些好的时间管理软件
  16. foxmail连接163邮箱服务器,Foxmail怎么接收163邮箱? foxmail添加163邮箱的方法
  17. 旅行商问题(回溯算法)
  18. gmx一定要在linux下运行么,gmx_mmpbsa使用说明
  19. H.264 AVCC header
  20. linux 三个特权位

热门文章

  1. oracle修改redo路径,oracle修改redo log files路径
  2. Oracle/PLSQL FETCH Statement
  3. 接口、抽象类、类之间的关系
  4. 【BZOJ1597】【Tyvj2461】土地购买,第一次的斜率优化DP
  5. ie8 html 语音标签,让IE8支持html5中的video标签
  6. 【英语学习】【Daily English】U13 Holiday L02 That's supposedly the best time of year to go
  7. ztree局部刷新节点_神经网络训练的世界记录是怎样被刷新的 -- 总结分布式训练的计算场景...
  8. Exception while invoking! org.apache.thrift.protocol.TProtocolException: Bad version in readMessageB
  9. MFC工程使用flash控件
  10. C语言标准库中常见字符串处理函数