QPainter 是 PySide6 中用于在小部件和其他绘图设备上进行低级绘图的类。
它提供了一系列的绘图函数,可以绘制从简单线条到复杂形状(如饼图和和弦图)的各种图形。
QPainter 还可以绘制对齐文本和图片。
通常,它使用“自然”坐标系进行绘图,但也支持视图和世界坐标转换。
from __future__ import annotations
import sys
from datetime import datetime
from PySide6.QtCore import QLine, QPoint, Qt
from PySide6.QtGui import QPainter, QPixmap
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow
def get_time_str() -> str:
return datetime.now().isoformat(sep = ' ')
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Hello, PySide6!')
self.setToolTip('A PySide6 GUI Application Demo')
# 设置画布大小
self.pixmap = QPixmap(400, 300)
self.pixmap.fill(Qt.GlobalColor.black)
# 在画布上绘制图线
self.painter = QPainter(self.pixmap)
self.painter.setPen(Qt.GlobalColor.red)
# 使用坐标画线
self.painter.drawLine(0, 0, 400, 300)
self.painter.drawLine(400, 0, 0, 300)
"""
如果不调用这个方法,那么这些资源可能会被锁定,导致无法被其他QPainter对象使用,
或者在某些情况下可能会导致内存泄漏,特别是当你在一个循环中多次使用QPainter对象时,
如果不调用end()方法,可能会导致程序崩溃或者运行效率降低
"""
self.painter.end()
# 使用 QLine 画线
self.painter = QPainter(self.pixmap)
self.painter.setPen(Qt.GlobalColor.blue)
self.painter.drawLine(QLine(0, 150, 400, 150))
self.painter.end()
# 使用 QPoint 画线
self.painter = QPainter(self.pixmap)
self.painter.setPen(Qt.GlobalColor.cyan)
self.painter.drawLine(QPoint(0, 100), QPoint(400, 100))
self.painter.end()
self.label = QLabel()
self.label.setPixmap(self.pixmap)
self.setCentralWidget(self.label)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
app.exec()
通常来说,使用 QPainter 画图的步骤为:
self.pixmap = QPixmap(400, 300)
self.painter = QPainter(self.pixmap)
self.painter.setPen(Qt.GlobalColor.red)
self.painter.drawxxxx
self.painter.end()
self.label.setPixmap(self.pixmap)
self.update()
from __future__ import annotations
import sys
from random import choice, randint
from PySide6.QtCore import QPoint, Qt
from PySide6.QtGui import QPainter, QPen, QPixmap
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Hello, PySide6!')
self.setToolTip('A PySide6 GUI Application Demo')
# 设置画布大小
self.pixmap = QPixmap(400, 300)
self.pixmap.fill(Qt.GlobalColor.black)
# 在画布上绘制图线
self.painter = QPainter(self.pixmap)
self.pen = QPen()
self.pen.setWidth(3)
self.pen.setColor(Qt.GlobalColor.red)
self.painter.setPen(self.pen)
colors = [x for x in Qt.GlobalColor]
# 使用坐标画线
for i in range(1, 10000):
self.pen.setColor(choice(colors))
# 这里需要每次都重新设置 pen,否则颜色不生效
# There can only ever be one QPen active on a QPainter
# -- the current pen.
self.painter.setPen(self.pen)
self.painter.drawPoint(QPoint(200 + randint(-100, 100), 150 + randint(-100, 100)))
"""
如果不调用这个方法,那么这些资源可能会被锁定,导致无法被其他QPainter对象使用,
或者在某些情况下可能会导致内存泄漏,特别是当你在一个循环中多次使用QPainter对象时,
如果不调用end()方法,会导致程序崩溃或者运行效率降低
"""
self.painter.end()
self.label = QLabel()
self.label.setPixmap(self.pixmap)
self.setCentralWidget(self.label)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
app.exec()
from __future__ import annotations
import sys
from PySide6.QtCore import QRect, Qt
from PySide6.QtGui import QBrush, QColor, QPainter, QPen, QPixmap
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Hello, PySide6!')
self.setToolTip('A PySide6 GUI Application Demo')
# 设置画布大小
self.pixmap = QPixmap(400, 300)
self.pixmap.fill(Qt.GlobalColor.black)
# 在画布上绘制图线
self.painter = QPainter(self.pixmap)
self.pen = QPen()
self.pen.setWidth(3)
self.pen.setColor(Qt.GlobalColor.red)
self.painter.setPen(self.pen)
# 第一个参数:x 坐标,表示矩形左上角的水平位置
# 第二个参数:y 坐标,表示矩形左上角的垂直位置
# 第三个参数:width,表示矩形的宽度
# 第四个参数:height,表示矩形的高度
self.painter.drawRect(10, 10, 200, 200)
self.pen.setColor(Qt.GlobalColor.blue)
self.painter.setPen(self.pen)
self.painter.drawRects([QRect(20, 20, 20, 20),
QRect(20, 20, 30, 30),
QRect(20, 20, 40, 40),
QRect(20, 20, 50, 50),
QRect(20, 20, 60, 60)])
self.pen.setColor(Qt.GlobalColor.green)
self.painter.setPen(self.pen)
self.brush = QBrush()
self.brush.setStyle(Qt.BrushStyle.SolidPattern)
self.brush.setColor(QColor("#FFD007"))
self.painter.setBrush(self.brush)
self.painter.drawRoundedRect(QRect(85, 85, 100, 100), 100, 100, Qt.SizeMode.RelativeSize)
"""
如果不调用这个方法,那么这些资源可能会被锁定,导致无法被其他QPainter对象使用,
或者在某些情况下可能会导致内存泄漏,特别是当你在一个循环中多次使用QPainter对象时,
如果不调用end()方法,可能会导致程序崩溃或者运行效率降低
"""
self.painter.end()
self.label = QLabel()
self.label.setPixmap(self.pixmap)
self.setCentralWidget(self.label)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
app.exec()
上述示例中,使用drawRect
、drawRects
、drawRoundedRect
分别绘制了矩形,其中,drawRoundedRect
中,当把曲率调位 100 时,矩形将会变为圆形。
from __future__ import annotations
import sys
from PySide6.QtCore import QPoint, Qt
from PySide6.QtGui import QBrush, QPainter, QPen, QPixmap
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Hello, PySide6!')
self.setToolTip('A PySide6 GUI Application Demo')
# 设置画布大小
self.pixmap = QPixmap(400, 300)
self.pixmap.fill(Qt.GlobalColor.black)
# 在画布上绘制图线
self.painter = QPainter(self.pixmap)
self.pen = QPen()
self.pen.setWidth(3)
self.pen.setColor(Qt.GlobalColor.green)
self.painter.setPen(self.pen)
self.brush = QBrush()
self.brush.setStyle(Qt.BrushStyle.SolidPattern)
self.brush.setColor(Qt.GlobalColor.red)
self.painter.setBrush(self.brush)
self.painter.drawEllipse(QPoint(200, 150), 100, 50)
"""
如果不调用这个方法,那么这些资源可能会被锁定,导致无法被其他QPainter对象使用,
或者在某些情况下可能会导致内存泄漏,特别是当你在一个循环中多次使用QPainter对象时,
如果不调用end()方法,可能会导致程序崩溃或者运行效率降低
"""
self.painter.end()
self.label = QLabel()
self.label.setPixmap(self.pixmap)
self.setCentralWidget(self.label)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
app.exec()
from __future__ import annotations
import sys
from datetime import datetime
from PySide6.QtCore import Qt
from PySide6.QtGui import QFont, QPainter, QPen, QPixmap
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Hello, PySide6!')
self.setToolTip('A PySide6 GUI Application Demo')
# 设置画布大小
self.pixmap = QPixmap(600, 400)
self.pixmap.fill(Qt.GlobalColor.black)
# 在画布上绘制图线
self.painter = QPainter(self.pixmap)
self.pen = QPen()
self.pen.setWidth(5)
self.pen.setColor(Qt.GlobalColor.darkMagenta)
self.painter.setPen(self.pen)
self.font = QFont('ComicShannsMono Nerd Font', 40)
# self.font.setBold(True)
self.painter.setFont(self.font)
self.painter.drawText(0, 0, 600, 400, Qt.AlignmentFlag.AlignCenter,
'Hello, PySide6!\n你好,GUI 编程!\n{}\n{}'.format(datetime.now().isoformat(), self.font.family()))
"""
如果不调用这个方法,那么这些资源可能会被锁定,导致无法被其他QPainter对象使用,
或者在某些情况下可能会导致内存泄漏,特别是当你在一个循环中多次使用QPainter对象时,
如果不调用end()方法,可能会导致程序崩溃或者运行效率降低
"""
self.painter.end()
self.label = QLabel()
self.label.setPixmap(self.pixmap)
self.setCentralWidget(self.label)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
app.exec()
from __future__ import annotations
import sys
from PySide6.QtCore import Qt
from PySide6.QtGui import QMouseEvent, QPainter, QPen, QPixmap
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Hello, PySide6!')
self.setToolTip('A PySide6 GUI Application Demo')
# 设置画布初始状态
self.pixmap = QPixmap(800, 600)
self.pixmap.fill(Qt.GlobalColor.white)
# 设置布局
self.label = QLabel()
self.label.setPixmap(self.pixmap)
self.button = QPushButton('清除所有')
self.button.clicked.connect(self.clear_all)
self.v_layout = QVBoxLayout()
self.v_layout.addWidget(self.label)
self.v_layout.addWidget(self.button)
self.container = QWidget()
self.container.setLayout(self.v_layout)
self.setCentralWidget(self.container)
# 鼠标坐标
self.last_x = None
self.last_y = None
def mouseMoveEvent(self, event: QMouseEvent) -> None:
pos = event.position()
if self.last_x is None and self.last_y is None:
self.last_x = pos.x()
self.last_y = pos.y()
return
# 在画布上绘制图线
painter = QPainter(self.pixmap)
pen = QPen()
pen.setWidth(3)
pen.setStyle(Qt.PenStyle.SolidLine)
pen.setCosmetic(True)
pen.setColor(Qt.GlobalColor.darkMagenta)
painter.setPen(pen)
painter.drawLine(self.last_x, self.last_y, int(pos.x()), int(pos.y()))
"""
如果不调用这个方法,那么这些资源可能会被锁定,导致无法被其他QPainter对象使用,
或者在某些情况下可能会导致内存泄漏,特别是当你在一个循环中多次使用QPainter对象时,
如果不调用end()方法,可能会导致程序崩溃或者运行效率降低
"""
painter.end()
# 更新QLabel中显示的内容,使其显示最新的QPixmap
self.label.setPixmap(self.pixmap)
# 记录上一次的鼠标坐标
self.last_x = pos.x()
self.last_y = pos.y()
# 显式刷新界面
self.update()
def mouseReleaseEvent(self, event: QMouseEvent) -> None:
self.last_x = None
self.last_y = None
def clear_all(self) -> None:
self.pixmap = QPixmap(800, 600)
self.pixmap.fill(Qt.GlobalColor.white)
self.label.setPixmap(self.pixmap)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
app.exec()
from __future__ import annotations
import sys
from PySide6.QtCore import Qt
from PySide6.QtGui import QMouseEvent, QPainter, QPen, QPixmap
from PySide6.QtWidgets import QApplication, QHBoxLayout, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Hello, PySide6!')
self.setToolTip('A PySide6 GUI Application Demo')
# 设置画布初始状态
self.pixmap = QPixmap(800, 600)
self.pixmap.fill(Qt.GlobalColor.white)
# 设置布局
self.label = QLabel()
self.label.setPixmap(self.pixmap)
# 颜色列表
self.colors_v_layout = QVBoxLayout()
colors_h_layout = QHBoxLayout()
self.colors_map = {}
colors_count = 0
for x in Qt.GlobalColor:
self.colors_map[x.name] = x
# css中没有 darkYellow 这种颜色,需要用 #CCCC00 来表示
# 因此为了逻辑上的方便,QPushButton 中不使用 darkYellow 来作为背景色
# 同时像 transparent、color0、color1 这样的颜色也过滤掉
# 由于画板的背景色已经是白色,因此这里也将 white 过滤掉
if x.name in ('transparent', 'white', 'color0', 'color1', 'darkYellow'):
continue
color_button = QPushButton(x.name)
style = """
QPushButton { background-color: %s; color: white; }
QPushButton:pressed { background-color: #CCCC00; }
""" % x.name
color_button.setStyleSheet(style)
color_button.clicked.connect(self.color_changed)
colors_h_layout.addWidget(color_button)
colors_count += 1
if colors_count % 9 == 0:
self.colors_v_layout.addLayout(colors_h_layout)
colors_h_layout = QHBoxLayout()
colors_count = 0
self.colors_v_layout.addLayout(colors_h_layout)
# 清除按钮
self.button = QPushButton('清除所有')
self.button.clicked.connect(self.clear_all)
# 布局
self.v_layout = QVBoxLayout()
self.v_layout.addWidget(self.label)
self.v_layout.addLayout(self.colors_v_layout)
self.v_layout.addWidget(self.button)
# 容器
self.container = QWidget()
self.container.setLayout(self.v_layout)
# 组件排布
self.setCentralWidget(self.container)
# 鼠标坐标
self.last_x = None
self.last_y = None
self.current_color = Qt.GlobalColor.darkMagenta
def mouseMoveEvent(self, event: QMouseEvent) -> None:
pos = event.position()
if self.last_x is None and self.last_y is None:
self.last_x = pos.x()
self.last_y = pos.y()
return
# 在画布上绘制图线
painter = QPainter(self.pixmap)
pen = QPen()
pen.setWidth(3)
pen.setStyle(Qt.PenStyle.SolidLine)
pen.setCosmetic(True)
pen.setColor(self.current_color)
painter.setPen(pen)
painter.drawLine(self.last_x, self.last_y, int(pos.x()), int(pos.y()))
"""
如果不调用这个方法,那么这些资源可能会被锁定,导致无法被其他QPainter对象使用,
或者在某些情况下可能会导致内存泄漏,特别是当你在一个循环中多次使用QPainter对象时,
如果不调用end()方法,可能会导致程序崩溃或者运行效率降低
"""
painter.end()
# 更新QLabel中显示的内容,使其显示最新的QPixmap
self.label.setPixmap(self.pixmap)
# 记录上一次的鼠标坐标
self.last_x = pos.x()
self.last_y = pos.y()
# 显式刷新界面
self.update()
def mouseReleaseEvent(self, event: QMouseEvent) -> None:
self.last_x = None
self.last_y = None
def clear_all(self) -> None:
self.pixmap = QPixmap(800, 600)
self.pixmap.fill(Qt.GlobalColor.white)
self.label.setPixmap(self.pixmap)
def color_changed(self) -> None:
self.current_color = self.colors_map[self.sender().text()]
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
app.exec()
from __future__ import annotations
import random
import sys
from cmath import pi
from PySide6.QtCore import Qt
from PySide6.QtGui import QMouseEvent, QPainter, QPen, QPixmap
from PySide6.QtWidgets import QApplication, QHBoxLayout, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Hello, PySide6!')
self.setToolTip('A PySide6 GUI Application Demo')
# 设置画布初始状态
self.pixmap = QPixmap(800, 600)
self.pixmap.fill(Qt.GlobalColor.white)
# 设置布局
self.label = QLabel()
self.label.setPixmap(self.pixmap)
# 颜色列表
self.colors_v_layout = QVBoxLayout()
colors_h_layout = QHBoxLayout()
self.colors_map = {}
colors_count = 0
for x in Qt.GlobalColor:
self.colors_map[x.name] = x
# css中没有 darkYellow 这种颜色,需要用 #CCCC00 来表示
# 因此为了逻辑上的方便,QPushButton 中不使用 darkYellow 来作为背景色
# 同时像 transparent、color0、color1 这样的颜色也过滤掉
# 由于画板的背景色已经是白色,因此这里也将 white 过滤掉
if x.name in ('transparent', 'white', 'color0', 'color1', 'darkYellow'):
continue
color_button = QPushButton(x.name)
style = """
QPushButton { background-color: %s; color: white; }
QPushButton:pressed { background-color: #CCCC00; }
""" % x.name
color_button.setStyleSheet(style)
color_button.clicked.connect(self.color_changed)
colors_h_layout.addWidget(color_button)
colors_count += 1
if colors_count % 9 == 0:
self.colors_v_layout.addLayout(colors_h_layout)
colors_h_layout = QHBoxLayout()
colors_count = 0
self.colors_v_layout.addLayout(colors_h_layout)
# 清除按钮
self.button = QPushButton('清除所有')
self.button.clicked.connect(self.clear_all)
# 布局
self.v_layout = QVBoxLayout()
self.v_layout.addWidget(self.label)
self.v_layout.addLayout(self.colors_v_layout)
self.v_layout.addWidget(self.button)
# 容器
self.container = QWidget()
self.container.setLayout(self.v_layout)
# 组件排布
self.setCentralWidget(self.container)
# 鼠标坐标
self.current_color = Qt.GlobalColor.darkMagenta
def mousePressEvent(self, event: QMouseEvent) -> None:
pos = event.position()
# 在画布上绘制图线
painter = QPainter(self.pixmap)
pen = QPen()
pen.setWidth(3)
pen.setStyle(Qt.PenStyle.SolidLine)
pen.setCosmetic(True)
pen.setColor(self.current_color)
painter.setPen(pen)
radius = 15
for _ in range(0, int(pi * (radius ** 2))):
x_offset = random.randint(0 - radius, radius)
y_offset = random.randint(0 - radius, radius)
# 画出一个半径为 radius 的圆
if int(x_offset) ** 2 + int(y_offset) ** 2 <= radius ** 2:
painter.drawPoint(int(pos.x() + x_offset), int(pos.y() + y_offset))
"""
如果不调用这个方法,那么这些资源可能会被锁定,导致无法被其他QPainter对象使用,
或者在某些情况下可能会导致内存泄漏,特别是当你在一个循环中多次使用QPainter对象时,
如果不调用end()方法,可能会导致程序崩溃或者运行效率降低
"""
painter.end()
# 更新QLabel中显示的内容,使其显示最新的QPixmap
self.label.setPixmap(self.pixmap)
# 显式刷新界面
self.update()
def clear_all(self) -> None:
self.pixmap = QPixmap(800, 600)
self.pixmap.fill(Qt.GlobalColor.white)
self.label.setPixmap(self.pixmap)
def color_changed(self) -> None:
self.current_color = self.colors_map[self.sender().text()]
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
app.exec()
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有