(PyQt5基本窗口控件(十)窗口绘图类控件)
十、窗口绘图类控件
- 在 PyQt5中,一般可以通过 QPainter,QPen和 QBrush 这三个类来实现绘图功能。此外,QPixmap的作用是加载并呈现本地图像,而图像的呈现本质上也是通过绘图方式实现的,所以 QPixmap也可以被视为绘图的一个类。
1、QPainter
- QPainter类在 QWidget(控件)上执行绘图操作,它是一个绘制工具,为大部分图形界面提供了高度优化的函数,使QPainter类可以绘制从简单的直线到复杂的饼图等。
- 绘制操作在 QWidget.paintEvent()中完成。绘制方法必须放在QtGui.QPainter对象的begin()和 end()之间。QPainter类在控件或其他绘图设备上执行较低级别的图形绘制功能。
- QPainter类中常用的方法
方法 | 描述 |
---|---|
begin() | 开始在目标设备上绘制 |
drawArc() | 在起始角度和最终角度之间画弧 |
drawEllipse | 在一个矩形内画一个椭圆 |
drawLine(int x1, int y1, int x2, int y2) | 绘制一条指定了端点坐标的线。绘制从(x1, y1)到(x2, y2)的直线并且设置当前画笔位置为(x2, y2) |
drawPixmap() | 从图像文件中提取Pixmap并将其显示在指定的位置 |
drawPolygon() | 使用坐标数组绘制多边形 |
drawRect(int x,int y,int w,int h) | 以给定的宽度w和高度h从左上角坐标(x,y)绘制一个矩形 |
drawText() | 显示给定坐标处的文字 |
fillRect() | 使用QColor参数填充矩形 |
setBrush() | 设置画笔风格 |
setPen() | 设置用于绘制的笔的颜色、大小和样式 |
- 画笔风格
枚举类型 | 描述 |
---|---|
Qt.NoPen | 没有线。比如 QPainter.drawRect()填充,但没有绘制任何边界线 |
Qt.SolidLine | 一条简单的线 |
Qt.DashLine | 由一些像素分隔的短信 |
Qt.DotLine | 由一些像素分隔的点 |
Qt.DashDotLine | 轮流交替的点和短线 |
Qt.DashDotDotLine | 一条短线、两个点 |
Qt.MPenStyle | 画笔风格的掩码 |
案例二十五 绘制文字
# -*- coding:utf-8 -*-
"""
# @Time:2022/12/9 0009 19:55
# @Author:晚秋拾叶
# @File:qt04_drawText.py
# @PyCharm之Python
"""
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QColor, QFont
from PyQt5.QtCore import Qt
class Drawing(QWidget):
def __init__(self, parent=None):
super(Drawing, self).__init__(parent)
self.setWindowTitle("在窗口中绘制文字")
self.resize(750, 200)
self.text = "愚钝半生无羁客,飘零晚秋拾落叶"
def paintEvent(self, event):
painter = QPainter(self)
painter.begin(self)
# 自定义绘制方法
self.drawText(event, painter)
painter.end()
def drawText(self, event, qp):
# 设置画笔的颜色
qp.setPen(QColor(168, 34, 3))
# 设置字体
qp.setFont(QFont('SimSun', 20))
# 绘制文字
qp.drawText(event.rect(), Qt.AlignCenter, self.text)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Drawing()
win.show()
sys.exit(app.exec_())
- 代码分析
- 首先定义要绘制的文字(其实是有屏幕上的一个个点point组成的),然后定义绘制事件,所有的绘制操作都发生在此事件内。代码如下
def paintEvent(self, event): painter = QPainter(self) painter.begin(self) # 调用自定义绘制方法 self.drawText(event, painter) painter.end()
- QtGui.QPainter类负责所有低级别的绘制,所有的绘制方法都要放在begin()和end()之间。
- 下面是自定义的drawText()方法
def drawText(self, event, qp): # 设置笔的颜色 qp.setPen(QColor(168, 34, 3)) # 设置字体 qp.setFont(QFont('simSun', 20) # 绘制文字 qp.drawText(event.rect(), Qt.AlignCenter, self.text)
- 首先定义要绘制的文字(其实是有屏幕上的一个个点point组成的),然后定义绘制事件,所有的绘制操作都发生在此事件内。代码如下
- 效果如图
案例二十六 绘制点
# -*- coding:utf-8 -*-
"""
# @Time:2022/12/9 0009 21:07
# @Author:晚秋拾叶
# @File:qt04_drawPoint.py
# @PyCharm之Python
"""
import math
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Drawing(QWidget):
def __init__(self, parent=None):
super(Drawing, self).__init__(parent)
self.setWindowTitle("在窗口中绘制点")
self.resize(400, 200)
def paintEvent(self, event):
# 初始化绘图工具
qp = QPainter()
# 开始在窗口中绘制
qp.begin(self)
# 自定义画点方法
self.drawPoint(qp)
# 结束在窗口中的绘制
qp.end()
def drawPoint(self, qp):
# 设置笔的颜色
qp.setPen(Qt.red)
# 获取当前窗口大小
size = self.size()
for i in range(1000):
# 绘制正弦函数图形,它的周期是[-100, 100]
x = 100 *(-1 + 2.0 * i / 1000) + size.width() / 2.0
y = -50 * math.sin((x - size.width() / 2.0) * math.pi / 50) + size.height() / 2.0
# 因为下面代码运行出现闪退,所以把(x, y)进行了int处理
# qp.drawPoint(x, y)
qp.drawPoint(int(x), int(y))
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Drawing()
win.show()
sys.exit(app.exec_())
- 代码分析
- 在这个例子中,在窗口的工作区绘制正弦函数图形,周期是-100到100
- 画笔是红色qp.setPen(Qt.red)
- 每次调整窗口大小时,都会生成一个绘图事件。使用size()方法得到窗口的当前大小,在新的窗口中随机分布工作区中的点。
size = self.size()
- 使用drawPoint()方法绘制一个个点。
# 因为下面代码运行出现闪退,所以把(x, y)进行了int处理 # qp.drawPoint(x, y) qp.drawPoint(int(x), int(y))
- 效果如图
2、QPen
- QPen(钢笔)是一个基本的图形对象,用于绘制直线、曲线或者给轮廓画出矩形、椭圆形、多边形及其他形状等
案例二十七 QPen的使用
# -*- coding:utf-8 -*-
"""
# @Time:2022/12/9 0009 22:43
# @Author:晚秋拾叶
# @File:qt04_drawPen.py
# @PyCharm之Python
"""
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt
class Drawing(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 280, 270)
self.setWindowTitle("钢笔样式案例")
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.drawLines(qp)
qp.end()
def drawLines(self, qp):
# 定义一个笔,并设置黑色、宽度2像素、SolidLine样式
pen = QPen(Qt.black, 2, Qt.SolidLine)
# 给函数传参
qp.setPen(pen)
qp.drawLine(20, 40, 250, 40)
pen.setStyle(Qt.DashLine)
qp.setPen(pen)
qp.drawLine(20, 80, 250, 80)
pen.setStyle(Qt.DashDotLine)
qp.setPen(pen)
qp.drawLine(20, 120, 250, 120)
pen.setStyle(Qt.DotLine)
qp.setPen(pen)
qp.drawLine(20, 160, 250, 160)
pen.setStyle(Qt.DashDotDotLine)
qp.setPen(pen)
qp.drawLine(20, 200, 250, 200)
# 这是自定义的线条样式
pen.setStyle(Qt.CustomDashLine)
pen.setDashPattern([1, 4, 5, 4])
qp.setPen(pen)
qp.drawLine(20, 240, 250, 240)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Drawing()
win.show()
sys.exit(app.exec_())
- 代码分析
- 在这个例子中,使用6种不同的线条样式绘制了6条线,其中前5条线使用的是预定义的线条样式。也可以自定义线条样式,最后一条线就是使用自定义的线条样式绘制的。
- 程序代码创建了一个QPen对象。为了能更清晰地看清各线之间的差异,将颜色设置成黑色,宽度设置为2像素(px)。Qt.SolidLine是预定义的线条样式之一。
pen = QPen(Qt.black, 2, Qt.solidLine)
- 以下代码自定义了一种线条样式。使用Qt.CustomDashLine创建线条样式,然后调用setDashPattern()方法使用数字列表定义样式。数字列表的个数必须是偶数,在本例中数字列表是[1,4,5,4],它的个数是4。在数字列表中,奇数位(数字列表中的第1,3,5等位置)代表一段横线,偶数位(数字列表中的第2,4,6等位置)代表两段横线之间的空余距离。在数字列表中数字越大,横线和空余距离就越大。本例中数字列表[1,4,5,4]代表的意义是:1像素宽度的横线,4像素宽度在空余距离,5像素宽度的横线,4像素宽度的空余距离。
pen.setStyle(Qt.CustomDashLine) pen.setDashPattern([1,4,5,4]) qp.setPen(pen) qp.drawLine(20, 240, 250, 240)
- 效果如图
3、QBrush
- QBrush(画刷)是一个基本的图形对象,用于填充如矩形、椭圆形或多边形等形状。QBrush有三种类型:预定义、过渡和纹理图案。
案例二十八 QBrush的使用
# -*- coding:utf-8 -*-
"""
# @Time:2022/12/10 0010 0:05
# @Author:晚秋拾叶
# @File:qt04_drawBrush.py
# @PyCharm之Python
【简介】
绘图中QBrush 的例子 ,绘制九个不同样式的矩形。
"""
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt
class Drawing(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 365, 280)
self.setWindowTitle('画刷案例')
self.show()
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.drawLines(qp)
qp.end()
def drawLines(self, qp):
brush = QBrush(Qt.SolidPattern)
qp.setBrush(brush)
qp.drawRect(10, 15, 90, 60)
brush = QBrush(Qt.Dense1Pattern)
qp.setBrush(brush)
qp.drawRect(130, 15, 90, 60)
brush = QBrush(Qt.Dense2Pattern)
qp.setBrush(brush)
qp.drawRect(250, 15, 90, 60)
brush = QBrush(Qt.Dense3Pattern)
qp.setBrush(brush)
qp.drawRect(10, 105, 90, 60)
brush = QBrush(Qt.DiagCrossPattern)
qp.setBrush(brush)
qp.drawRect(10, 105, 90, 60)
brush = QBrush(Qt.Dense5Pattern)
qp.setBrush(brush)
qp.drawRect(130, 105, 90, 60)
brush = QBrush(Qt.Dense6Pattern)
qp.setBrush(brush)
qp.drawRect(250, 105, 90, 60)
brush = QBrush(Qt.HorPattern)
qp.setBrush(brush)
qp.drawRect(10, 195, 90, 60)
brush = QBrush(Qt.VerPattern)
qp.setBrush(brush)
qp.drawRect(130, 195, 90, 60)
brush = QBrush(Qt.BDiagPattern)
qp.setBrush(brush)
qp.drawRect(250, 195, 90, 60)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Drawing()
win.show()
sys.exit(app.exec_())
-
代码分析
-
在这个例子中,在窗口中绘制出9种不同背景填充的矩形。
-
以下代码定义了QBrush对象,然后将QPainter对象的画刷设置成QBrush对象,并通过调用drawRect()方法绘制矩形。
brush = QBrush(Qt.SolidPattern) qp.setBrush(brush) qp.drawRect(10, 15, 90, 60)
-
-
效果如图
4、QPixmap
-
QPixmap类用于绘图设备的图像显示,它可以作为一个QPaintDevice对象,也可以加载到一个控件中,通常是标签或按钮,用于在标签或按钮上显示图像。 QPixmap可以读取的图像文件类型有BMP、GIF、JPG、JPEG、PNG、PBM、PGM、PPM、XBM 、XPM等。
-
QPixmap类中常用方法
方法 | 描述 |
---|---|
copy() | 从 QRect对象复制到QPixmap对象 |
fromImage() | 将 Qlmage对象转换为QPixmap对象 |
grabWidget() | 从给定的窗口小控件创建一个像素图 |
grabWindow() | 在窗口中创建数据的像素图 |
load() | 加载图像文件作为 QPixmap对象 |
save() | 将QPixmap对象保存为文件 |
toImage() | 将QPixmap对象转换为QImage对象 |
案例二十九 QPixmap的使用
# -*- coding:utf-8 -*-
"""
# @Time:2022/12/10 0010 0:27
# @Author:晚秋拾叶
# @File:qt04_QPixmap.py
# @PyCharm之Python
"""
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
if __name__ == '__main__':
app = QApplication(sys.argv)
win = QWidget()
lab1 = QLabel()
lab1.setPixmap(QPixmap("./images/child.jpg"))
vbox = QVBoxLayout()
vbox.addWidget(lab1)
win.setLayout(vbox)
win.setWindowTitle("QPixmap 例子")
win.show()
sys.exit(app.exec_())
- 代码分析
-
在这个例子中,使用setPixmap()将图像显示在QLabel上。
lab1 = QLabel() lab1.setPixmap("./images/child.jpg"))
-
上面的“./”代表程序运行目录(打开的目录)
-
- 效果如图