PySide6 中的 QPainter 和位图图形
摘要:本文介绍了PySide6中QPainter的核心功能及其在绘制位图图形中的应用。主要内容包括:1. QPainter的基本用法,如绘制点、线、矩形、椭圆和文本;2. 通过设置画笔(QPen)和画刷(QBrush)控制图形样式;3. 构建一个简易绘图应用程序的完整示例,支持线条绘制和颜色选择;4. 实现喷绘效果的扩展功能。文章还对比了位图与矢量图形的区别,并展示了如何通过鼠标事件实现交互式绘图
PySide6 中的 QPainter 和位图图形
QPainter核心功能简介
在 PyQt5 中创建自定义控件的第一步是理解位图(基于像素)图形操作。所有标准控件都以位图的形式绘制在构成控件形状的矩形“画布”上。一旦你理解了它的工作原理,你就可以绘制任何你想要的控件了!
位图是由像素组成的矩形网格,其中每个像素都单独存储为若干比特。这与矢量图形不同,矢量图形中的图像存储为一系列重复执行的绘图指令,从而形成图像。
在本教程中,我们将了解QPainterQt 的 API,它用于执行位图图形操作,并奠定绘制自定义控件的基础。我们将学习一些基本的绘图操作,最后将所有内容整合起来,创建一个我们自己的简易绘图应用程序。

QPainter
在 Qt 中,位图绘制操作由 `Pixmap` 类处理QPainter。这是一个通用接口,可用于在各种表面上绘制图形,例如 `<div>` 和 `<div> QPixmap`。为了便于演示,我们将使用以下示例应用程序,该程序负责创建容器(`<div>` QLabel)、创建位图画布、在容器中显示位图以及将容器添加到主窗口。
import sys
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import Qt
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.label = QtWidgets.QLabel()
canvas = QtGui.QPixmap(400, 300)
canvas.fill(Qt.white)
self.label.setPixmap(canvas)
self.setCentralWidget(self.label)
self.draw_something()
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
painter.drawLine(10, 10, 300, 200)
painter.end()
self.label.setPixmap(canvas)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
为什么我们用它QLabel来绘制图形?该QLabel控件还可以用来显示图像,它是目前最简单的用于显示图形的控件QPixmap。
在 PySide2 中,我们可以直接在标签内的 像素图上绘制图形。但在 PySide6 中,我们需要先获取像素图self.label.pixmap(),对其进行修改,然后再将其应用到标签上。第二种方法在 PySide2 中也适用,因此我们将在下文中使用它。
Martin Fitzpatrick 的《使用 PyInstaller 打包 Python 应用程序》 ——本分步指南将引导您完成 Python 应用程序的打包,从简单的示例到完整的安装程序和签名可执行文件。
将此保存到文件中并运行,您应该会看到以下内容——窗口框内有一条黑线——

画布上只有一条黑线。
所有绘制操作都在draw_something方法内部完成——我们创建一个QPainter实例,传入画布(self.label.pixmap()),然后发出绘制线条的命令。最后,我们调用.end()关闭绘制器并应用更改。
通常还需要调用方法.update()来触发小部件的刷新,但由于我们在应用程序窗口显示之前进行绘制,因此已经会发生刷新。
绘制基本图形
QPainter它提供了大量用于在位图表面上绘制形状和线条的方法(在 5.12 版本中,有 192 个QPainter特定的非事件方法)。好消息是,其中大多数是重载方法,它们只是调用相同基方法的不同方式。
例如,有 5 种不同的drawLine方法,它们都画出同一条线,但绘制该线的坐标定义方式不同。
| 方法 | 描述 |
|---|---|
drawLine(line) |
绘制一个QLine实例 |
drawLine(line) |
绘制一个QLineF实例 |
drawLine(x1, y1, x2, y2) |
在 x1, y2 和 x2, y2 之间画一条线 ( int) |
drawLine(p1, p2) |
在 p1 和 p2 之间画一条线(两者都要画QPoint)。 |
drawLine(p1, p2) |
在 p1 和 p2 之间画一条线(两者都要画QPointF)。 |
QLine如果你想知道 a和 a之间的区别QLineF,后者是用 指定的坐标float。如果你已经通过其他计算得到了浮点位置,这很方便,但除此之外就没什么用了。
忽略 F 变体,我们有三种独特的方式来绘制直线——使用直线对象、使用两组坐标(x1, y1), (x2, y2) 或使用两个QPoint对象。当你发现 `a`QLine本身被定义为 `a`QLine(const QPoint & p1, const QPoint & p2)或 `b`QLine(int x1, int y1, int x2, int y2)时,你会发现它们实际上完全相同。不同的调用签名仅仅是为了方便。
给定 x1、y1、x2、y2 坐标,这两个QPoint对象将被定义为QPoint(x1, y1)和QPoint(x2, y2)。
去掉重复项,我们有以下绘图操作—— ,,,,,,,,,,,,,drawArc和drawChord。为了避免不知所措drawConvexPolygon,我们将首先专注于基本形状和线条,并在掌握基础知识后再回过头来学习更复杂的操作。drawEllipsedrawLinedrawPathdrawPiedrawPointdrawPolygondrawPolylinedrawRectdrawRectsdrawRoundedRect
对于每个示例,请替换draw_something存根应用程序中的方法并重新运行它以查看输出。
绘制点
这段代码会在画布上的指定位置绘制一个点(或像素)drawPoint 。每次调用都会绘制一个像素。请将你的draw_something代码替换为以下代码。
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
painter.drawPoint(200, 150)
painter.end()
self.label.setPixmap(canvas)
如果重新运行该文件,你会看到一个窗口,但这次窗口中间会有一个黑色的点。你可能需要移动窗口才能看到它。

使用 QPainter 绘制单个点(像素)
这看起来确实没什么特别的。为了让画面更有趣,我们可以改变绘制点的颜色和大小。在 PyQt 中,线条的颜色和粗细是通过QPainter 上的活动画笔QPen来定义的。你可以通过创建一个实例并应用它来进行设置。
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(40)
pen.setColor(QtGui.QColor('red'))
painter.setPen(pen)
painter.drawPoint(200, 150)
painter.end()
self.label.setPixmap(canvas)
这将带来以下略微有趣的结果……

一个大大的红点。
您可以随意执行多次绘制操作,QPainter直到绘图程序结束。在画布上绘制非常快——这里我们随机绘制了 1 万个点。
from random import randint # add this import at the top of the file.
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(3)
painter.setPen(pen)
for n in range(10000):
painter.drawPoint(
200+randint(-100, 100), # x
150+randint(-100, 100) # y
)
painter.end()
self.label.setPixmap(canvas)
这些点宽为 3 像素,颜色为黑色(默认画笔)。

画布上的 1 万个 3 像素点
在绘图过程中,您经常需要更新当前画笔——例如,在保持其他属性(例如宽度)不变的情况下,绘制多个不同颜色的点。为了避免每次都创建新的画笔实例,您可以使用`using` 方法QPen获取当前活动的画笔。您还可以多次重新应用现有的画笔,每次都进行更改。QPainterpen = painter.pen()
from random import randint, choice # add this import at the top of the file.
def draw_something(self):
colors = ['#FFD141', '#376F9F', '#0D1F2D', '#E9EBEF', '#EB5160']
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(3)
painter.setPen(pen)
for n in range(10000):
# pen = painter.pen() you could get the active pen here
pen.setColor(QtGui.QColor(choice(colors)))
painter.setPen(pen)
painter.drawPoint(
200+randint(-100, 100), # x
150+randint(-100, 100) # y
)
painter.end()
self.label.setPixmap(canvas)
将产生以下输出——

随机排列的3个宽度的点
QPen一支笔上 只能有一个活动笔QPainter——即当前笔。
在屏幕上画点所能带来的兴奋感也就到此为止了,所以我们接下来将去看一些其他的绘图操作。
画线
我们一开始已经在画布上画了一条线来测试功能是否正常。但我们没有尝试设置画笔来控制线条的外观。
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(15)
pen.setColor(QtGui.QColor('blue'))
painter.setPen(pen)
painter.drawLine(
QtCore.QPoint(100, 100),
QtCore.QPoint(300, 200)
)
painter.end()
self.label.setPixmap(canvas)
在这个例子中,我们也使用QPoint定义要用直线连接的两个点,而不是传递单独的x1, y1, x2, y2参数——记住,这两种方法在功能上是相同的。

一条粗蓝线
drawRect、drawRects 和 drawRoundedRect
这些函数都绘制矩形,矩形由矩形的坐标和 a 定义x,或者由提供y等效信息的实例定义。widthheightQRectQRectF
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(3)
pen.setColor(QtGui.QColor("#EB5160"))
painter.setPen(pen)
painter.drawRect(50, 50, 100, 100)
painter.drawRect(60, 60, 150, 100)
painter.drawRect(70, 70, 100, 150)
painter.drawRect(80, 80, 150, 100)
painter.drawRect(90, 90, 100, 150)
painter.end()
self.label.setPixmap(canvas)
正方形就是宽度和高度都相同的长方形。

绘制矩形
你也可以drawRect用一次调用并drawRects传入多个QRect对象来替换多次调用。这样会产生完全相同的结果。
painter.drawRects(
QtCore.QRect(50, 50, 100, 100),
QtCore.QRect(60, 60, 150, 100),
QtCore.QRect(70, 70, 100, 150),
QtCore.QRect(80, 80, 150, 100),
QtCore.QRect(90, 90, 100, 150),
)
在 PyQt 中,可以通过设置当前活动的画笔,并传入一个QBrush实例来填充绘制的形状painter.setBrush()。以下示例将所有矩形填充为带有图案的黄色。
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(3)
pen.setColor(QtGui.QColor("#376F9F"))
painter.setPen(pen)
brush = QtGui.QBrush()
brush.setColor(QtGui.QColor("#FFD141"))
brush.setStyle(Qt.Dense1Pattern)
painter.setBrush(brush)
painter.drawRects([
QtCore.QRect(50, 50, 100, 100),
QtCore.QRect(60, 60, 150, 100),
QtCore.QRect(70, 70, 100, 150),
QtCore.QRect(80, 80, 150, 100),
QtCore.QRect(90, 90, 100, 150),
])
painter.end()
self.label.setPixmap(canvas)

填充矩形
至于画笔,每个画家的笔刷一次只能激活一支,但你可以在绘画过程中切换或更换画笔。有很多笔刷样式可供选择。不过,你可能会用到Qt.SolidPattern最常用的几种。
您必须设置样式才能看到任何填充效果,因为默认值为Qt.NoBrush
这些drawRoundedRect方法绘制一个矩形,但边缘是圆角,因此需要两个额外的参数来表示角的x 和 y半径。
from random import randint # add this import at the top of the file.
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(3)
pen.setColor(QtGui.QColor("#376F9F"))
painter.setPen(pen)
painter.drawRoundedRect(40, 40, 100, 100, 10, 10)
painter.drawRoundedRect(80, 80, 100, 100, 10, 50)
painter.drawRoundedRect(120, 120, 100, 100, 50, 10)
painter.drawRoundedRect(160, 160, 100, 100, 50, 50)
painter.end()
self.label.setPixmap(canvas)

圆角矩形。
还有一个可选的最终参数,用于切换椭圆角点的 x 和 y 半径是以绝对像素值Qt.RelativeSize(默认值)还是相对于矩形大小(以 0…100 为值传递)定义的。传递此参数Qt.RelativeSize以启用此功能。
绘制椭圆
我们现在要介绍的最后一个基本绘图方法是,drawEllipse它可以用来绘制椭圆或圆。
使用 Python 和 Qt6 创建 GUI 应用程序 (作者:Martin Fitzpatrick )——(PyQt6 版)使用 Python 制作应用程序的实用指南——销量超过 10,000 册!
圆其实就是宽度和高度相等的椭圆。
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(3)
pen.setColor(QtGui.QColor(204,0,0)) # r, g, b
painter.setPen(pen)
painter.drawEllipse(10, 10, 100, 100)
painter.drawEllipse(10, 10, 150, 200)
painter.drawEllipse(10, 10, 200, 300)
painter.end()
self.label.setPixmap(canvas)
在这个例子中,它需要 4 个参数,前两个参数是绘制椭圆的矩形左上角drawEllipse的 x 和 y 位置,后两个参数分别是该矩形的宽度和高度。

绘制具有 x、y、宽度、高度或 QRect 的椭圆。
您可以通过传入一个参数来实现同样的效果。QRect
还有另一种调用签名,它将椭圆的中心作为第一个参数(以QPoint对象QPointF形式提供),然后是 ax 和 y轴半径。下面的示例展示了它的实际应用。
painter.drawEllipse(QtCore.QPoint(100, 100), 10, 10)
painter.drawEllipse(QtCore.QPoint(100, 100), 15, 20)
painter.drawEllipse(QtCore.QPoint(100, 100), 20, 30)
painter.drawEllipse(QtCore.QPoint(100, 100), 25, 40)
painter.drawEllipse(QtCore.QPoint(100, 100), 30, 50)
painter.drawEllipse(QtCore.QPoint(100, 100), 35, 60)

利用点和半径绘制椭圆。
填充椭圆的设置方式与QBrush填充矩形相同,样式和颜色等功能也相同。
文本
最后,我们简要了解一下QPainter文本绘制方法。要控制当前字体,QPainter需要setFont传入一个QFont实例。通过这种方式,您可以控制所写文本的字体系列、粗细和大小(以及其他属性)。但是,文本的颜色仍然由当前画笔定义。
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
pen = QtGui.QPen()
pen.setWidth(1)
pen.setColor(QtGui.QColor('green'))
painter.setPen(pen)
font = QtGui.QFont()
font.setFamily('Times')
font.setBold(True)
font.setPointSize(40)
painter.setFont(font)
painter.drawText(100, 100, 'Hello, world!')
painter.end()
self.label.setPixmap(canvas)
您还可以使用QPoint或指定位置QPointF。
笔的粗细对文字的外观没有影响。

位图文本“Hello World”示例。
还有一些方法可以在指定区域内绘制文本。这里的参数定义了边界框的 x 和 y 坐标以及宽度和高度。超出此框的文本将被裁剪(隐藏)。第五个参数标志可用于控制框内文本的对齐方式等。
painter.drawText(100, 100, 100, 100, Qt.AlignHCenter, 'Hello, world!')

drawText 时边界框被裁剪。
您可以通过对象在绘图器上设置活动字体,从而完全控制文本的显示。有关更多信息,QFont请参阅QFont 文档。
用 QPainter 做点有趣的事
刚才讲的内容有点深奥,我们来轻松一下,做点有趣的事情。到目前为止,我们一直在用编程的方式定义要执行的绘制操作。但我们也可以很容易地根据用户输入进行绘制——例如,允许用户在画布上随意涂鸦。在这一部分,我们将运用目前所学的知识,构建一个简易的绘图应用程序。
我们可以从同样的简单应用程序框架开始,用一个mouseMoveEvent事件处理程序MainWindow替换类中的绘制方法。在这里,我们将获取用户鼠标的当前位置,并在画布上绘制一个点。
import sys
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import Qt
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.label = QtWidgets.QLabel()
canvas = QtGui.QPixmap(400, 300)
canvas.fill(Qt.white)
self.label.setPixmap(canvas)
self.setCentralWidget(self.label)
def mouseMoveEvent(self, e):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
painter.drawPoint(e.x(), e.y())
painter.end()
self.label.setPixmap(canvas)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
为什么没有点击事件?默认情况下,控件仅在按下鼠标按钮时接收鼠标移动事件,除非启用了鼠标跟踪.setMouseTracking。可以使用该方法进行配置——将其设置为True(默认情况下已False启用)将持续跟踪鼠标。
保存并运行此程序后,您应该能够移动鼠标并在屏幕上点击来绘制单个点。它应该看起来像这样——

绘制单个鼠标移动事件点。
问题在于,当你快速移动鼠标时,它实际上会在屏幕上的不同位置之间跳跃,而不是平滑地从一个位置移动到另一个位置。虽然mouseMoveEvent鼠标所在的每个位置都会触发一次事件,但这不足以绘制一条连续的线条,除非你移动得非常慢。
解决这个问题的方法是画线而不是点。对于每个事件,我们只需从之前的位置(e.x()和e.y())画一条线到现在的位置(e.x()和e.y())。我们可以通过跟踪last_x和last_y自身来实现这一点。
我们也需要在释放鼠标时忘记鼠标的最后位置,否则在将鼠标移动到页面上后,我们将再次从该位置开始绘制——也就是说,我们将无法断开线条。
import sys
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import Qt
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.label = QtWidgets.QLabel()
canvas = QtGui.QPixmap(400, 300)
canvas.fill(Qt.white)
self.label.setPixmap(canvas)
self.setCentralWidget(self.label)
self.last_x, self.last_y = None, None
def mouseMoveEvent(self, e):
if self.last_x is None: # First event.
self.last_x = e.x()
self.last_y = e.y()
return # Ignore the first time.
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
painter.drawLine(self.last_x, self.last_y, e.x(), e.y())
painter.end()
self.label.setPixmap(canvas)
# Update the origin for next time.
self.last_x = e.x()
self.last_y = e.y()
def mouseReleaseEvent(self, e):
self.last_x = None
self.last_y = None
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
运行此程序后,您应该能够像预期那样在屏幕上涂鸦。

用鼠标绘制,使用连续线条。
它现在看起来还是有点单调,所以我们添加一个简单的调色板,以便我们可以改变画笔颜色。
这需要对架构进行一些重新设计。目前我们一直使用 ` mouseMoveEventon` 属性QMainWindow。当窗口中只有一个控件时,这样做没问题——只要窗口大小不超过控件大小(你试过吗?),容器和嵌套控件的坐标就能对齐。但是,如果我们在布局中添加其他控件,这种方法就行不通了——控件的坐标QLabel会相对于窗口发生偏移,导致绘制位置错误。
这个问题很容易解决,只需将鼠标处理移到对象QLabel本身即可——它的事件坐标始终相对于自身。我们将其封装成一个自定义Canvas对象,该对象负责创建像素图表面,设置 x 和 y 坐标,并保存当前画笔颜色(默认为黑色)。
这是一个独立的、Canvas可直接插入的可绘制表面,您可以在自己的应用程序中使用它。
import sys
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import Qt
class Canvas(QtWidgets.QLabel):
def __init__(self):
super().__init__()
pixmap = QtGui.QPixmap(600, 300)
pixmap.fill(Qt.white)
self.setPixmap(pixmap)
self.last_x, self.last_y = None, None
self.pen_color = QtGui.QColor('#000000')
def set_pen_color(self, c):
self.pen_color = QtGui.QColor(c)
def mouseMoveEvent(self, e):
if self.last_x is None: # First event.
self.last_x = e.x()
self.last_y = e.y()
return # Ignore the first time.
canvas = self.pixmap()
painter = QtGui.QPainter(canvas)
p = painter.pen()
p.setWidth(4)
p.setColor(self.pen_color)
painter.setPen(p)
painter.drawLine(self.last_x, self.last_y, e.x(), e.y())
painter.end()
self.setPixmap(canvas)
# Update the origin for next time.
self.last_x = e.x()
self.last_y = e.y()
def mouseReleaseEvent(self, e):
self.last_x = None
self.last_y = None
为了实现颜色选择,我们将基于现有组件构建一个自定义组件QPushButton。该组件接受一个color参数,该参数可以是QColour实例、颜色名称(例如“红色”、“黑色”)或十六进制值。此颜色将设置为组件的背景色,使其易于识别。我们可以使用标准QPushButton.pressed信号将其连接到任何操作。
COLORS = [
# 17 undertones https://lospec.com/palette-list/17undertones
'#000000', '#141923', '#414168', '#3a7fa7', '#35e3e3', '#8fd970', '#5ebb49',
'#458352', '#dcd37b', '#fffee5', '#ffd035', '#cc9245', '#a15c3e', '#a42f3b',
'#f45b7a', '#c24998', '#81588d', '#bcb0c2', '#ffffff',
]
class QPaletteButton(QtWidgets.QPushButton):
def __init__(self, color):
super().__init__()
self.setFixedSize(QtCore.QSize(24,24))
self.color = color
self.setStyleSheet("background-color: %s;" % color)
定义了这两个新部分之后,我们只需要遍历颜色列表,创建一个QPaletteButton颜色传递,将其按下信号连接到set_pen_color画布上的处理程序(通过lambda传递额外的颜色数据间接连接),并将其添加到调色板布局中。
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.canvas = Canvas()
w = QtWidgets.QWidget()
l = QtWidgets.QVBoxLayout()
w.setLayout(l)
l.addWidget(self.canvas)
palette = QtWidgets.QHBoxLayout()
self.add_palette_buttons(palette)
l.addLayout(palette)
self.setCentralWidget(w)
def add_palette_buttons(self, layout):
for c in COLORS:
b = QPaletteButton(c)
b.pressed.connect(lambda c=c: self.canvas.set_pen_color(c))
layout.addWidget(b)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
这样您就可以使用功能齐全的多色绘画应用程序,在画布上绘制线条并从调色板中选择颜色。

可惜的是,这并不能让你成为一名优秀的艺术家。
喷 (pen 这个翻译着实有点。。。尴尬)
最后,为了增加一些趣味性,你可以将 `<br>` 替换mouseMoveEvent为以下代码,用“喷漆罐”效果而不是线条来绘制图形。这是通过random.gauss生成一系列围绕当前鼠标位置呈正态分布的drawPoint点来模拟的,我们用 `<br>` 绘制这些点。
def mouseMoveEvent(self, e):
canvas = self.pixmap()
painter = QtGui.QPainter(canvas)
p = painter.pen()
p.setWidth(1)
p.setColor(self.pen_color)
painter.setPen(p)
for n in range(SPRAY_PARTICLES):
xo = random.gauss(0, SPRAY_DIAMETER)
yo = random.gauss(0, SPRAY_DIAMETER)
painter.drawPoint(e.x() + xo, e.y() + yo)
self.setPixmap(canvas)
在文件顶部定义 ` SPRAY_PARTICLESand`变量,并导入标准库模块。下图显示了使用以下设置时的喷雾行为:SPRAY_DIAMETERrandom
import random
SPRAY_PARTICLES = 100
SPRAY_DIAMETER = 10

对于喷罐来说,我们不需要跟踪之前的位置,因为我们总是围绕当前点进行喷洒。
如果你想挑战一下自己,可以尝试添加一个额外的按钮来切换绘制和喷涂模式,或者添加一个输入来定义画笔/喷雾直径。
想要体验用 PyQt5 编写的功能齐全的绘图程序,请查看我的15 分钟应用程序“Piecasso”。
这篇介绍应该让你对它的功能有了大致的了解QPainter。正如前面提到的,这个系统是所有控件绘制的基础。如果你想深入了解,可以查看控件.paint()方法,该方法接收一个QPainter实例,允许控件在自身上绘制图形。你在这里学到的方法同样可以用于.paint()绘制一些基本的自定义控件。我们将在下一篇教程中详细讲解。
更多推荐


所有评论(0)