![f71d3899a82564e79fca08a69aa5f252.png](https://i-blog.csdnimg.cn/blog_migrate/687bbef2bb09228b6c16acbd4fa84fbd.jpeg)
绘图操作主要通过QPainter类来进行,通过该类我们可以绘制许多种几何图形(点、线、矩形、椭圆、饼状图等等),当然也可以用来绘制图像和文字。本章首先来介绍QPainter类,之后再结合QPrinter类来了解下如何给程序加上打印功能。
31.1 画笔、画刷和字体
绘图操作通常在paintEvent()事件函数中完成。在该函数中,我们一般会先对画笔、画刷或者字体进行设置然后再调用相关方法进行绘制。
画笔用来画线和边缘,我们可以设置其颜色,线型和宽度等,下图是Qt提供的几种内置线型风格:
![72609883c9f32b2baf4b5a57095f2d2f.png](https://i-blog.csdnimg.cn/blog_migrate/8f66e26dd4a056454394122c5e727582.jpeg)
画刷用来对几何图形进行填充,我们同样可以设置其颜色和填充风格。下图是Qt提供的画刷风格:
![9a4a645fbb59b39a6203e334fbef2d60.png](https://i-blog.csdnimg.cn/blog_migrate/c0da3534779696d05fe569b8823232ed.jpeg)
可以看出最后个Qt::TexturePattern风格可以让我们刷出给定的图像。
字体用来绘制文字,我们可以设置其字体种类和大小,就是调用QPainter类的setFont()方法传入QFont类型参数(之前章节其实已经了解过该方法)
首先来了解下画笔QPen:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtWidgets import QApplication, QWidget
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.resize(600, 600)
self.pen1 = QPen() # 1
self.pen1.setColor(Qt.green)
self.pen2 = QPen(Qt.SolidLine)
self.pen2.setWidth(6) # 2
# self.pen2.setWidthF(3.3)
self.pen3 = QPen(Qt.DashLine)
self.pen4 = QPen(Qt.DotLine)
self.pen5 = QPen(Qt.DashDotLine)
self.pen6 = QPen(Qt.DashDotDotLine)
self.pen7 = QPen(Qt.CustomDashLine) # 3
self.pen7.setDashPattern([6, 2, 18, 2])
self.pen8 = QPen(Qt.SolidLine) # 4
self.pen8.setWidth(6)
self.pen8.setCapStyle(Qt.RoundCap)
self.pen9 = QPen(Qt.SolidLine) # 5
self.pen9.setWidthF(6)
self.pen9.setJoinStyle(Qt.MiterJoin)
def paintEvent(self, QPaintEvent):
painter = QPainter(self) # 6
painter.setPen(self.pen1)
painter.drawLine(100, 10, 500, 10)
painter.setPen(self.pen2)
painter.drawLine(100, 30, 500, 30)
painter.setPen(self.pen3)
painter.drawLine(100, 50, 500, 50)
painter.setPen(self.pen4)
painter.drawLine(100, 70, 500, 70)
painter.setPen(self.pen5)
painter.drawLine(100, 90, 500, 90)
painter.setPen(self.pen6)
painter.drawLine(100, 110, 500, 110)
painter.setPen(self.pen7)
painter.drawLine(100, 130, 500, 130)
painter.setPen(self.pen8)
painter.drawLine(100, 150, 500, 150)
painter.setPen(self.pen2)
painter.drawRect(100, 170, 400, 200) # 7
painter.setPen(self.pen9)
painter.drawRect(100, 390, 400, 200)
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())
1. 实例化QPen对象,可直接传入画笔样式(默认为Qt.SolidLine),调用setColor()方法可设置画笔颜色;
2. 调用setWidth()方法传入整型值,可设置画笔粗细(默认为1)。如果要传入浮点型的话可使用setWidthF();
3. 使用Qt.CustomDashLine自定义样式的话,我们之后还需要调用setDashPattern()方法来设置虚线模式。只要传入一个迭代器即可,这里我们传入[6, 2, 18, 2]这个列表,意思是我们想将第一个虚线长度设为6个像素,再设置空白间隔长度为2个像素,之后再画一条长度为18像素的虚线,最后再加个长度为2像素的空白间隔,如此循环。
我们现在看下文档是怎么描述该方法的:
![7e7a4f71604b1af1ca14e098d370ceb7.png](https://i-blog.csdnimg.cn/blog_migrate/95ad7efe5c300feb875e849ef0c949d4.jpeg)
有两点我们还需要注意:
- 虽然文档上说元素数量必须为偶数,但笔者传入有5个元素的列表(例如[6, 2, 18, 2, 13])发现其实也可以。小伙伴可以自己去看下PyQt5是怎么绘制此类模式的。
- 虚线长度跟画笔宽度和笔端样式(后面会讲到)相关。若画笔宽度为10的话,那长度值5就代表50个像素。若笔端样式为Qt.SquareCap(默认值)的话,那每条虚线都其实会在每一端延伸出【画笔宽度/2】个像素值。pen7画笔的宽度为1,笔端样式为Qt.SquareCap。那也就是说[6, 2, 18, 2]中的数字6和18所设置的虚线宽度其实是7和19。当然,这里只是了解下,如果程序绘图不需要这么精确的话,小伙伴们可以不需要考虑这点。
4. 调用setCapStyle()设置笔端样式为Qt.RoundCap,一共有以下三种笔端样式:
![a0598813bbb4f130ee8b495c87b28a9b.png](https://i-blog.csdnimg.cn/blog_migrate/8222bf47619a29b69deff25e587d77af.jpeg)
5. 调用setJoinStyle()设置线条连接方式为Qt.MiterJoin,一共有以下三种:
![daadaf0b59021fd34f0667d87c9ac0ad.png](https://i-blog.csdnimg.cn/blog_migrate/f7b5934ddcef36bad412b3c7501e3dd2.jpeg)
6. 在paintEvent()事件函数中实例化一个QPainter对象,调用setPen()方法设置画笔,之后再调用drawLine()方法传入坐标就可以画出一条直线了。
7. 为了对比连接方式,我们用pen2和pen9各画了一个矩形(直线是没有连接处的)。
运行截图如下:
![f9742da19cb0d12d21bbc1e178858da3.png](https://i-blog.csdnimg.cn/blog_migrate/6623c7ef23e53ebc971be9be2555c6bb.jpeg)
接下来是画刷(样式太多,笔者挑一些来讲):
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QBrush, QPixmap, QLinearGradient, QRadialGradient, QConicalGradient
from PyQt5.QtWidgets import QApplication, QWidget
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.resize(600, 600)
self.brush1 = QBrush(Qt.SolidPattern) # 1
self.brush2 = QBrush(Qt.Dense6Pattern) # 2
self.brush2.setColor(Qt.red)
gradient1 = QLinearGradient(200, 200, 300, 300) # 3
gradient1.setColorAt(0.2, Qt.red)
gradient1.setColorAt(0.8, Qt.green)
gradient1.setColorAt(1, Qt.blue)
self.brush3 = QBrush(gradient1)
gradient2 = QRadialGradient(350, 350, 50, 350, 350) # 4
gradient2.setColorAt(0, Qt.red)
gradient2.setColorAt(1, Qt.blue)
self.brush4 = QBrush(gradient2)
gradient3 = Q