QPaintDevice是所有可以进行绘制的对象的基类,它的子类主要有QWidget、QPixmap、QPicture、QImage、QPrinter和QOpenGLPaintDevice等。
QPaintEngine类应用于QPainter和QPaintDevice之间,通常对开发人员是透明的。除非你需要自定义一个设备,否则你是不需要关心QPaintEngine这个类的。除了创建自定义的绘图设备类型,一般编程中不需要使用该类。(本篇作为入门文章,就不再讲这个了)
![]()
上面的示意图告诉我们,Qt 的绘图系统实际上是,使用QPainter在QPainterDevice上进行绘制,它们之间使用QPaintEngine进行通讯(也就是翻译QPainter的指令)。
先看一个基本例子
class PaintedWidget : public QWidget
{
Q_OBJECT
public:
PaintedWidget(QWidget *parent = 0);
protected:
void paintEvent(QPaintEvent *)override;
};
PaintedWidget::PaintedWidget(QWidget *parent) :
QWidget(parent)
{
resize(800, 600);
setWindowTitle(tr("Paint Demo"));
}
// 绘制
void PaintedWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawLine(80, 100, 650, 500);
painter.setPen(Qt::red); // setPen 设置轮廓线的颜色
painter.drawRect(10, 10, 100, 400);
painter.setPen(QPen(Qt::green, 5));
painter.setBrush(Qt::blue); // brush是画刷,是填充颜色
painter.drawEllipse(50, 150, 400, 200);
}
首先,我们在栈上创建了一个QPainter对象,也就是说,每次运行paintEvent()函数的时候,都会重建这个QPainter对象。注意,这一点可能会引发某些细节问题:由于我们每次重建QPainter,因此第一次运行时所设置的画笔颜色、状态等,第二次再进入这个函数时就会全部丢失。有时候我们希望保存画笔状态,就必须自己保存数据,否则的话则需要将QPainter作为类的成员变量。
基本的绘制和填充
绘图系统中由QPainter完成具体的绘制操作,其中,提供了大量高度优化的函数(一般draw开头)来完成GUI编程所需要的大部分绘工作。
QPainter可以绘制一切想要的图形,从最简单的一条直线到其他任何复杂的图形,还可以绘制文本和图片。
QPainter可以在继承自QPaintDevice类的任何对象上进行绘制操作(QWidget,QImage等),QPaintDevice可以理解成要在哪里去绘制。(对于上例子的中,我们希望画在这个组件,因此传入的是 this 指针。)
QPainter一般在一个部件重绘事件(Paint Event)的处理函数paintEvent()中进行绘制,首先要创建QPainter对象,然后进行图形的绘制,最后销毁QPainter对象。
绘制图形
// 方式1
void Widget::paintEvent(QPaintEvent *){
QPainter painter(this);
painter.drawLine(80, 100, 650, 500);
// 或者下面 (drawLine有)
painter.drawLine(QPoint(0,0),QPoint(100,100));
}
//方式2 ,与上面等价
void Widget::paintEvent(QPaintEvent *) {
QPainter painter;
painter.begin(this);
painter.drawLine(QPoint(0,0),QPoint(100,100));
painter.end();
}
第一种方式创建时并指定了this为绘图设备,即表明在Widget部件上进行绘制。这个构造函数创建的对象会立即开始在设备上进行绘制,自动调用begin()函数,然后在QPainter的析构函数中调用end()函数结束绘制。
第二种:如果构建QPainter对象时不想指定绘制设备,那么可以使用不带参数的构造函数,然后使用QPainter:: begin(QPaintDevice *device)在开始绘制时指定绘制设备,等绘制完成后再调用end()函数结束绘制。
常用的绘制方法
使用画笔(QPen)
The QPen class defines how a QPainter should draw lines and outlines of shapes.(QPen类定义QPainter应该如何绘制形状的线条和轮廓)
详细内容请看doc
For example:
QPainter painter(this);
QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);
painter.setPen(pen);
which is equivalent to
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);
QPen(const QBrush &brush, qreal width, Qt::PenStyle style = Qt::SolidLine, Qt::PenCapStyle cap = Qt::SquareCap, Qt::PenJoinStyle join = Qt::BevelJoin)
这个构造函数参数依次是画刷,线宽,画笔风格,画笔端点风格和画笔连线风格。
然后使用painter的setPen()来设置画笔。
Pen Style(画笔风格)
还可以使用setDashPattern()函数来自定义一个画笔风格。
doc有说明
QPen pen;
QVector<qreal> dashes;
qreal space = 4;
dashes << 1 << space << 3 << space << 9 << space
<< 27 << space << 9 << space;
pen.setDashPattern(dashes);
Cap Style(画笔端点风格) The default is Qt::SquareCap.
Join Style(画笔连接风格) The default is Qt::BevelJoin.
画笔连接风格定义了怎样绘制两个线条的连接。
其中,Qt::BeveJoin风格填充了两个线条之间的空缺三角形;
而Qt:: RoundJoin使用圆弧来填充这个三角形,这样显得更圆滑;
使用Qt:: MiterJoin风格,是将两个线条的外部边线进行扩展而相交,然后填充形成的三角形区域。
注意:这3种风格对于宽度为0的线条没有作用,可以把很宽的线条看作一个矩形来理解这3种风格,如下:
使用画刷(QBrush)
QBrush类提供了画刷来对图形进行填充,一个画刷使用它的颜色和风格(比如它的填充模式)来定义。
在Qt中使用的颜色一般都由QColor类(此类与平台无关)来表示,它支持RGB、HSV和CMYK等颜色模型。Qt提供了20多种的预定义颜色。
渐变填充(QGradinet) —详细查看和派生的三个类
上面提到了在画刷中可以使用渐变填充。QGradient类就是用来和QBrush一起指定渐变填充的。
Qt现在支持3种类型的渐变填充:
线性渐变(linear gradient):在开始点和结束点之间插入颜色;(QLineGradient)
辐射渐变(radialgradient):在焦点和环绕它的圆环间插人颜色;(QRadialGradient)
锥形渐变(Conical):在圆心周围插入颜色(QConicalGradient)
- Qt中2D绘图问题总结(一)----------基本的绘制与填充
刚刚开始学习Qt不久,才开始渐渐地熟悉基础内容,学习过程中的一些知识的总结和感悟希望通过博客记录下来,与大家分享学习的同时,也是对自己坚持下去的鞭策,废话不多说了,开始第一次的小总结吧. Qt提供了强 ...
- iOS:quartz2D绘图(给图形绘制阴影)
quartz2D既可以绘制原始图形,也可以给原始图形绘制阴影. 绘制阴影时,需要的一些参数:上下文.阴影偏移量.阴影模糊系数 注意:在drawRect:方法中同时调用绘制同一个图形时,在对绘制的图形做 ...
- 界面编程之QT绘图和绘图设备20180728
/*******************************************************************************************/ 一.绘图 整 ...
- matlab学习笔记8 基本绘图命令-初级二维绘图/交互式绘图
一起来学matlab-matlab学习笔记8 基本绘图命令_5 初级二维绘图/交互式绘图 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用&g ...
- 三维数据曲面图 season绘图 panda绘图
三维数据曲面图 season绘图 panda绘图 待办 enter description here 转化成网格坐标 season可以让绘图更美观 panda绘图可以直接根据panda数据绘制图直接p ...
- CAD参数绘制图案填充(网页版)
绘制工程图,常常需要将某种图案填充到某一区域,例如剖面线的绘制.MxCAD提供了丰富的填充图案,可以利用这些图案进行快速填充. js中实现代码说明: function DrawPathToHatch2 ...
- Canvas绘图中的路径描边与填充
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .网站上有对应每一 ...
- UIKit和Core Graphics绘图(三)——绘制虚线,椭圆以及饼图
绘制虚线 虚线绘制主要调用CGContextSetLineDash函数. 这个函数有4个参数,除了一个是上下文外,phase为初始跳过几个点开始绘制,第三个参数为一个CGFloat数组,指定你绘制的样 ...
- R绘图 第九篇:绘制散点图和气泡图(ggplot2)
绘制散点图(scatterplots)使用geom_point()函数,气泡图(bubblechart)也是一个散点图,只不过点的大小由一个变量(size)来控制.散点图潜在的最大问题是过度绘图:当一 ...
随机推荐
- Optional 容器类
什么是Optional容器类 Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的 ...
- Perl入门 - Perl方法的使用
1.定义一个方法 Perl使用sub定义方法. 语法: sub 方法名称{方法体} 2.调用一个方法 Perl直接使用方法名称调用方法. 调用方式有以下四种: 方法名称: &方法名称: 方法名 ...
- elasticserach数据库深度分页查询的原理
深度分页存在的问题 https://segmentfault.com/a/1190000019004316?utm_source=tag-newest 在实际应用中,分页是必不可少的,例如,前端页面展 ...
- StringEscapeUtils防止xss攻击详解
StringUtils和StringEscapeUtils这两个实用类. 1.转义防止xss攻击 1.转义可以分为下面的几种情况 第一用户输入特殊字符的时候,在提及的时候不做任何处理保持到数据库,当用 ...
- 关于MySQL事务和存储引擎常见FAQ
1.什么是事务? 事务就是「一组原子性的SQL查询」,或者说一个独立的工作单元.如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询.如果其中有任何一条语句因为崩溃或其他原因无法 ...
- java基础-循环标签
outer: for innter: for break outer//跳出整个循环: continue outer//结束本次外循环的循环 break inner; continute inner; ...
- MongoDB快速入门教程 (3.2)
3.2.索引 索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,建立索引,通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条 ...
- vue基础入门(2.2)
2.2.基础指令 2.2.1.什么是指令 指令 (Directives) 是带有 v- 前缀的特殊特性,指令特性的值预期是单个 JavaScript 表达式,指令的职责是,当表达式的值改变时,将其产生 ...
- js语法基础入门(4)
4.运算符 4.1.什么是运算符? 运算符就是用来表示具体运算规则的符号,例如数学计算中的加减乘除就是具体的运算规则,我们分别用"+ - * /"等符号来表示 4.2.运算符的分类 ...
- Python数据分析帮你清晰的了解整理员工们的工作效率和整体满意度
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 项目背景 2018年,被称为互联网的寒冬之年.无论大小公司,纷纷走上了裁员 ...