PyQt5提供了绘制图形的API,支持绘制:
- 文本
- 各种图形(直线,点,椭圆,弧,扇形,多边形等)
- 图像
绘制图形需要一个类QPainter
。基本的绘制过程:
# 创建QPainter对象
painter = QPainter()
# painter初始化
painter.begin()
# 绘制文本
painter.drawText(...)
# 结束绘制
painter.end()
还有需要注意的是,绘制的场所必须是在painterEvent
方法中。而这个painterEvent
事件的方法会在主窗口刚刚生成时调用(生成绘制的图形)、调整主窗口大小时调用(随着主窗口的大小比例调整绘制图像的大小比例)和关闭主窗口时调用(销毁绘制的图形)
在窗口上绘制文本
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class DrawText(QWidget):def __init__(self):super(DrawText, self).__init__()self.setWindowTitle("在窗口上绘制文本")self.resize(300, 200)self.text = "Hello world"
def paintEvent(self, event):painter = QPainter(self)painter.begin(self)# 加一个输出,观察什么情况下print("Done")# 设置画笔颜色painter.setPen(QColor(150, 43, 5))# 设置字体painter.setFont(QFont("SimSun", 25))# 指定绘图区域,对齐方式和绘制内容painter.drawText(event.rect(), Qt.AlignCenter, self.text)painter.end()
if __name__ == '__main__':app = QApplication(sys.argv)main = DrawText()main.show()sys.exit(app.exec_())
运行结果:
窗口刚刚弹出时,移动窗口时,放大放小窗口时,关闭窗口时。控制台上都打印了“Done”,说明在这几类情况下,主事件调用了paintEvent()
方法
需要注意的是,paintEvent()
是内置的事件方法,我们只是重载了,故初始化中没有调用paintEvent()
,但是,实际上主循环内部自动地调用了它。所以,这个方法的名字不是我们任意起的,而是固定的(如果不是paintEvent()
而是其他什么的,程序就无法正常显示绘制的内容)。
还有需要注意的是,使用painter.begin()
初始化时,为了体现是固定在主窗口上创建的,必须要填入参数self
。
对于其中的painter.drawText()
方法,需要说明其中的第一个参数:
painter.drawText(event.rect(), Qt.AlignCenter, self.text)
第一个参数是指定的绘图区域,此处的event.rect()
指的是主事件的矩形区域,也就是整个主窗口,除此之外,可以通过指定x和y来指定绘图区域,后面会讲解。
用像素点绘制正弦曲线
PyQt5中的drawPoint
可以绘制一个像素点,参数是x与y。
import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class DrawPoints(QWidget):def __init__(self):super(DrawPoints, self).__init__()self.setWindowTitle("用像素点绘制正弦曲线")self.resize(300, 300)
def paintEvent(self, event):painter = QPainter()painter.begin(self)
painter.setPen(Qt.blue)size = self.size()
for i in range(1000):x = 100 * (-1 + 2 * i / 1000) + size.width() / 2y = -50 * math.sin((x - size.width() / 2) * math.pi / 50) + size.height() / 2painter.drawPoint(int(x), int(y))painter.end()
if __name__ == '__main__':app = QApplication(sys.argv)main = DrawPoints()main.show()sys.exit(app.exec_())
运行效果:
绘制不同类型的直线
import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class DrawMultiLine(QWidget):def __init__(self):super(DrawMultiLine, self).__init__()self.setWindowTitle("绘制不同类型的直线")self.resize(300, 300)
def paintEvent(self, event):painter = QPainter()painter.begin(self)
# 颜色, 粗细, 线条类型(默认为Qt.SolidLine,即实线)pen = QPen(Qt.red, 3, Qt.SolidLine)painter.setPen(pen)painter.drawLine(20, 40, 250, 40)
# 点线pen.setStyle(Qt.DashDotLine)painter.setPen(pen)painter.drawLine(20 ,80, 250, 80)
# 点点线pen.setStyle(Qt.DashDotDotLine)painter.setPen(pen)painter.drawLine(20, 120, 250 ,120)
# 自定义点线风格pen.setStyle(Qt.CustomDashLine)pen.setDashPattern([1, 10, 5, 8])painter.setPen(pen)painter.drawLine(20, 200, 250, 200)
painter.end()
if __name__ == '__main__':app = QApplication(sys.argv)main = DrawMultiLine()main.show()sys.exit(app.exec_())
运行结果:
drawLine(a, b, c, d)
:从坐标为(a,b)的点绘制到(c,d)的点的线段。- 窗口坐标系:(a,b)代表离窗口左侧为a个像素点,离窗口最上侧为b个像素点。
绘制各种图形
绘制弧
import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class DrawAll(QWidget):def __init__(self):super(DrawAll, self).__init__()self.setWindowTitle("绘制各种图形")self.resize(300, 300)
def paintEvent(self, event):qp = QPainter()qp.begin(self)
qp.setPen(Qt.blue)
# 绘制弧# 先选定绘制区域,绘制区域为矩形(QRect)# 左上角坐标为(0, 10), 长为100, 宽为100rect = QRect(0, 10, 100, 100)# 弧为圆的一部分,角度的单位是alen:1个alen等于1/16度# 下面在rect代表的区域中绘制,起始角度为0,终止角度为50度(50 * 16 alen)qp.drawArc(rect, 0, 50 * 16)
qp.end()
if __name__ == '__main__':app = QApplication(sys.argv)main = DrawAll()main.show()sys.exit(app.exec_())
运行结果:
绘制圆:
# 通过弧绘制圆
qp.setPen(Qt.red)
qp.drawArc(120, 10, 100, 100, 0, 360 * 16)
运行结果:
可以看到,除了使用QRect
对象指定绘图区域,我们还可以直接初始化QRect
的四个参数直接填入drawArc
函数中作为前四个参数;起始位置为0,终止为止为360度的弧就是圆。
绘制带弦的弧:
# 绘制带弦的弧
qp.drawChord(10, 120, 100, 100, 12, 130 * 16)
运行结果:
绘制扇形
# 绘制扇形
qp.drawPie(10, 240, 100, 100, 12, 130 * 16)
运行结果:
绘制椭圆
# 绘制椭圆
qp.drawEllipse(120, 120, 150, 100)
运行结果:
绘制椭圆只需要指定绘图区域,绘制出的椭圆就是指定的矩形区域的内接椭圆。所以,我们可以通过指定正方形区域来绘制圆。
绘制5边形
# 绘制5边形
point1 = QPoint(140, 380)
point2 = QPoint(270, 420)
point3 = QPoint(290, 512)
point4 = QPoint(290, 588)
point5 = QPoint(200, 533)
polygon = QPolygon([point1, point2, point3, point4, point5])
qp.drawPolygon(polygon)
运行结果:
多边形的绘制机制也蛮显然的,通过创建多个QPoint
对象指定多边形的每个顶点的坐标,再用这几个代表像素点的QPoint
对象去初始化一个QPolygon
对象,这个QPolygon
对象作为drawPolygon
的参数完成绘制。
绘制图像
# 绘制图像
image = QImage("./image/pic2.png")
rect = QRect(300, 200, 300, 230)
qp.drawImage(rect, image)
运行结果:
用画刷填充图形区域
import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class FillRect(QWidget):def __init__(self):super(FillRect, self).__init__()self.setWindowTitle("用画刷填充图形区域")self.resize(360, 300)
def paintEvent(self, event):qp = QPainter()qp.begin(self)
# 实心画刷brush = QBrush(Qt.SolidPattern)qp.setBrush(brush)qp.drawRect(10, 15, 90, 60)
# 点阵画刷(类型1)brush = QBrush(Qt.Dense1Pattern)qp.setBrush(brush)qp.drawRect(130, 15, 90, 60)
# 点阵画刷(类型2)brush = QBrush(Qt.Dense2Pattern)qp.setBrush(brush)qp.drawRect(250, 15, 90, 60)
# 点阵画刷(类型3)brush = QBrush(Qt.Dense3Pattern)qp.setBrush(brush)qp.drawRect(10, 105, 90, 60)
# 点阵画刷(类型4)brush = QBrush(Qt.Dense4Pattern)qp.setBrush(brush)qp.drawRect(130, 105, 90, 60)
# 点阵画刷(类型5)brush = QBrush(Qt.Dense5Pattern)qp.setBrush(brush)qp.drawRect(250, 105, 90, 60)
# 点阵画刷(类型6)brush = QBrush(Qt.Dense6Pattern)qp.setBrush(brush)qp.drawRect(10, 195, 90, 60)
# 点阵画刷(类型7)brush = QBrush(Qt.Dense7Pattern)qp.setBrush(brush)qp.drawRect(130, 195, 90, 60)
# 横格画刷brush = QBrush(Qt.HorPattern)qp.setBrush(brush)qp.drawRect(250, 195, 90, 60)
qp.end()
if __name__ == '__main__':app = QApplication(sys.argv)main = FillRect()main.show()sys.exit(app.exec_())
运行结果:
每创建一个画刷对象,都需要调用QPainter
对象的setBrush()
方法设置画刷。