ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# PyQt5 中的绘图 > 原文: [http://zetcode.com/gui/pyqt5/painting/](http://zetcode.com/gui/pyqt5/painting/) PyQt5 绘图系统能够呈现向量图形,图像和轮廓基于字体的文本。 当我们想要更改或增强现有的小部件,或者从头开始创建自定义小部件时,应用中需要绘图。 要进行绘制,我们使用 PyQt5 工具包提供的绘制 API。 ## `QPainter` `QPainter`在小部件和其他绘图设备上执行低级绘图。 它可以绘制从简单的线条到复杂形状的所有内容。 ## `paintEvent`方法 绘图是在`paintEvent()`方法中完成的。 绘图代码位于`QPainter`对象的`begin()`和`end()`方法之间。 它在小部件和其他绘图设备上执行低级绘图。 ## 绘制文字 我们首先在窗口的客户区域上绘制一些 Unicode 文本。 `drawingtext.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- """ ZetCode PyQt5 tutorial In this example, we draw text in Russian Cylliric. Author: Jan Bodnar Website: zetcode.com Last edited: August 2017 """ import sys from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.QtGui import QPainter, QColor, QFont from PyQt5.QtCore import Qt class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.text = "Лев Николаевич Толстой\nАнна Каренина" self.setGeometry(300, 300, 280, 170) self.setWindowTitle('Drawing text') self.show() def paintEvent(self, event): qp = QPainter() qp.begin(self) self.drawText(event, qp) qp.end() def drawText(self, event, qp): qp.setPen(QColor(168, 34, 3)) qp.setFont(QFont('Decorative', 10)) qp.drawText(event.rect(), Qt.AlignCenter, self.text) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_()) ``` 在我们的示例中,我们以西里尔字母绘制一些文本。 文本在垂直和水平方向上对齐。 ```py def paintEvent(self, event): ... ``` 绘制是在绘画事件中完成的。 ```py qp = QPainter() qp.begin(self) self.drawText(event, qp) qp.end() ``` `QPainter`类负责所有低级绘图。 所有绘图方法都在`begin()`和`end()`方法之间。 实际绘图将委托给`drawText()`方法。 ```py qp.setPen(QColor(168, 34, 3)) qp.setFont(QFont('Decorative', 10)) ``` 在这里,我们定义了用于绘制文本的笔和字体。 ```py qp.drawText(event.rect(), Qt.AlignCenter, self.text) ``` `drawText()`方法在窗口上绘制文本。 绘画事件的`rect()`方法返回需要更新的矩形。 使用`Qt.AlignCenter`,我们可以在两个维度上对齐文本。 ![Drawing text](https://img.kancloud.cn/4a/94/4a948266454bb125d58c91a0b708f824_282x195.jpg) 图:绘制文本 ## 绘制点 点是可以绘制的最简单的图形对象。 这是窗口上的一个小地方。 `points.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- """ ZetCode PyQt5 tutorial In the example, we draw randomly 1000 red points on the window. Author: Jan Bodnar Website: zetcode.com Last edited: August 2017 """ from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.QtGui import QPainter from PyQt5.QtCore import Qt import sys, random class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 300, 190) self.setWindowTitle('Points') self.show() def paintEvent(self, e): qp = QPainter() qp.begin(self) self.drawPoints(qp) qp.end() def drawPoints(self, qp): qp.setPen(Qt.red) size = self.size() for i in range(1000): x = random.randint(1, size.width()-1) y = random.randint(1, size.height()-1) qp.drawPoint(x, y) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_()) ``` 在我们的示例中,我们在窗口的客户区域上随机绘制了 1000 个红点。 ```py qp.setPen(Qt.red) ``` 我们将笔设置为红色。 我们使用预定义的`Qt.red`颜色常量。 ```py size = self.size() ``` 每次我们调整窗口大小时,都会生成一个绘制事件。 我们使用`size()`方法获得窗口的当前大小。 我们使用窗口的大小将点分布在整个窗口的客户区域中。 ```py qp.drawPoint(x, y) ``` 我们用`drawPoint()`方法画点。 ![Points](https://img.kancloud.cn/77/d0/77d0cba230aa99d065f7fa7a465ada23_302x215.jpg) 图:点 ## 颜色 颜色是代表红色,绿色和蓝色(RGB)强度值的组合的对象。 有效的 RGB 值在 0 到 255 之间。我们可以通过多种方式定义颜色。 最常见的是 RGB 十进制值或十六进制值。 我们还可以使用代表红色,绿色,蓝色和 Alpha 的 RGBA 值。 在这里,我们添加了一些有关透明度的额外信息。 Alpha 值为 255 表示完全不透明,0 表示完全透明,例如颜色是不可见的。 `colours.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- """ ZetCode PyQt5 tutorial This example draws three rectangles in three #different colours. Author: Jan Bodnar Website: zetcode.com Last edited: August 2017 """ from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.QtGui import QPainter, QColor, QBrush import sys class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 350, 100) self.setWindowTitle('Colours') self.show() def paintEvent(self, e): qp = QPainter() qp.begin(self) self.drawRectangles(qp) qp.end() def drawRectangles(self, qp): col = QColor(0, 0, 0) col.setNamedColor('#d4d4d4') qp.setPen(col) qp.setBrush(QColor(200, 0, 0)) qp.drawRect(10, 15, 90, 60) qp.setBrush(QColor(255, 80, 0, 160)) qp.drawRect(130, 15, 90, 60) qp.setBrush(QColor(25, 0, 90, 200)) qp.drawRect(250, 15, 90, 60) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_()) ``` 在我们的示例中,我们绘制了三个彩色矩形。 ```py color = QColor(0, 0, 0) color.setNamedColor('#d4d4d4') ``` 在这里,我们使用十六进制符号定义颜色。 ```py qp.setBrush(QColor(200, 0, 0)) qp.drawRect(10, 15, 90, 60) ``` 在这里,我们定义了一个画笔并绘制了一个矩形。笔刷是用于绘制形状背景的基本图形对象。 `drawRect()`方法接受四个参数。 前两个是轴上的 x 和 y 值。 第三个和第四个参数是矩形的宽度和高度。 该方法使用当前的笔和画笔绘制矩形。 ![Colours](https://img.kancloud.cn/96/62/9662e6cbc52cdf83fc41896775025ec9_352x125.jpg) 图:颜色 ## 笔 `QPen`是基本图形对象。 它用于绘制矩形,椭圆形,多边形或其他形状的线,曲线和轮廓。 `pens.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- """ ZetCode PyQt5 tutorial In this example we draw 6 lines using different pen styles. Author: Jan Bodnar Website: zetcode.com Last edited: August 2017 """ from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.QtGui import QPainter, QPen from PyQt5.QtCore import Qt import sys class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 280, 270) self.setWindowTitle('Pen styles') self.show() def paintEvent(self, e): qp = QPainter() qp.begin(self) self.drawLines(qp) qp.end() def drawLines(self, qp): 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) ex = Example() sys.exit(app.exec_()) ``` 在我们的示例中,我们绘制了六条线。 线条以六种不同的笔样式绘制。 有五种预定义的笔样式。 我们还可以创建自定义笔样式。 最后一行是使用自定义笔样式绘制的。 ```py pen = QPen(Qt.black, 2, Qt.SolidLine) ``` 我们创建一个`QPen`对象。 颜色是黑色。 宽度设置为 2 像素,以便我们可以看到笔样式之间的差异。 `Qt.SolidLine`是预定义的笔样式之一。 ```py pen.setStyle(Qt.CustomDashLine) pen.setDashPattern([1, 4, 5, 4]) qp.setPen(pen) ``` 在这里,我们定义了自定义笔样式。 我们设置`Qt.CustomDashLine`笔样式并调用`setDashPattern()`方法。 数字列表定义样式。 数字必须是偶数。 奇数定义笔划线,偶数空格。 数字越大,空格或笔划线越大。 我们的模式是 1px 笔划线,4px 间隔,5px 笔划线,4px 间隔等。 ![Pen styles](https://img.kancloud.cn/9e/dc/9edc965427c0ee5f361c272813646a26_282x295.jpg) 图:笔的样式 ## `QBrush` `QBrush`是基本图形对象。 它用于绘制图形形状的背景,例如矩形,椭圆形或多边形。 笔刷可以具有三种不同类型:预定义笔刷,渐变或纹理图案。 `brushes.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- """ ZetCode PyQt5 tutorial This example draws nine rectangles in different brush styles. Author: Jan Bodnar Website: zetcode.com Last edited: August 2017 """ from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.QtGui import QPainter, QBrush from PyQt5.QtCore import Qt import sys class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 355, 280) self.setWindowTitle('Brushes') self.show() def paintEvent(self, e): qp = QPainter() qp.begin(self) self.drawBrushes(qp) qp.end() def drawBrushes(self, qp): brush = QBrush(Qt.SolidPattern) qp.setBrush(brush) qp.drawRect(10, 15, 90, 60) brush.setStyle(Qt.Dense1Pattern) qp.setBrush(brush) qp.drawRect(130, 15, 90, 60) brush.setStyle(Qt.Dense2Pattern) qp.setBrush(brush) qp.drawRect(250, 15, 90, 60) brush.setStyle(Qt.DiagCrossPattern) qp.setBrush(brush) qp.drawRect(10, 105, 90, 60) brush.setStyle(Qt.Dense5Pattern) qp.setBrush(brush) qp.drawRect(130, 105, 90, 60) brush.setStyle(Qt.Dense6Pattern) qp.setBrush(brush) qp.drawRect(250, 105, 90, 60) brush.setStyle(Qt.HorPattern) qp.setBrush(brush) qp.drawRect(10, 195, 90, 60) brush.setStyle(Qt.VerPattern) qp.setBrush(brush) qp.drawRect(130, 195, 90, 60) brush.setStyle(Qt.BDiagPattern) qp.setBrush(brush) qp.drawRect(250, 195, 90, 60) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_()) ``` 在我们的示例中,我们绘制了九个不同的矩形。 ```py brush = QBrush(Qt.SolidPattern) qp.setBrush(brush) qp.drawRect(10, 15, 90, 60) ``` 我们定义一个笔刷对象。 我们将其设置为绘画器对象,并通过调用`drawRect()`方法绘制矩形。 ![Brushes](https://img.kancloud.cn/a5/56/a556f19bace97af52b6ba0301694af7b_357x305.jpg) 图:笔刷 ## 贝塞尔曲线 贝塞尔曲线是一条三次曲线。 可以使用`QPainterPath`创建 PyQt5 中的贝塞尔曲线。 画家路径是由许多图形构造块(例如矩形,椭圆形,直线和曲线)组成的对象。 `beziercurve.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- """ ZetCode PyQt5 tutorial This program draws a Bézier curve with QPainterPath. Author: Jan Bodnar Website: zetcode.com Last edited: August 2017 """ from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.QtGui import QPainter, QPainterPath from PyQt5.QtCore import Qt import sys class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 380, 250) self.setWindowTitle('Bézier curve') self.show() def paintEvent(self, e): qp = QPainter() qp.begin(self) qp.setRenderHint(QPainter.Antialiasing) self.drawBezierCurve(qp) qp.end() def drawBezierCurve(self, qp): path = QPainterPath() path.moveTo(30, 30) path.cubicTo(30, 30, 200, 350, 350, 30) qp.drawPath(path) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_()) ``` 本示例绘制了贝塞尔曲线。 ```py path = QPainterPath() path.moveTo(30, 30) path.cubicTo(30, 30, 200, 350, 350, 30) ``` 我们使用`QPainterPath`路径创建贝塞尔曲线。 曲线是通过`cubicTo()`方法创建的,该方法需要三个点:起点,控制点和终点。 ```py qp.drawPath(path) ``` 使用`drawPath()`方法绘制最终路径。 ![Bézier curve](https://img.kancloud.cn/9c/39/9c399f20bea8209861da33b1c87661b7_382x275.jpg) 图:贝塞尔曲线 在 PyQt5 教程的这一部分中,我们做了一些基本的绘图。