QPainter 绘图
运用 PyQt6 QGui 的 QPainter 模组,就能在视窗里绘制各种形状,或进行放入文字和图片的动作,这篇教学会介绍如何在 PyQt6 视窗里使用 QPainter。
快速导览:
因为 Google Colab 不支援 PyQt6,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda )。
开始使用 QPainter
使用 QPainter 最基本需要 import QPainter 和 QPen 模组,并额外 import QColor 设定颜色,接着在建立 PyQt6 视窗对象后,修改视窗对象的 paintEvent 属性,将该属性的内容设定为绘图的内容,执行后就会看见视窗出现红色正方形。
from PyQt6 import QtWidgets
from PyQt6.QtGui import QPainter, QColor, QPen
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(300, 200)
# 定義繪圖的函式,注意需要包含 self 參數
def draw(self):
qpainter = QPainter() # 建立繪圖器
qpainter.begin(MainWindow) # 在 MainWindow 開始繪圖
qpainter.setPen(QPen(QColor('#ff0000'),5)) # 設定畫筆顏色和寬度
qpainter.drawRect(50, 50, 100, 100) # 繪製正方形
qpainter.end() # 結束繪圖
MainWindow.paintEvent = draw # 設定 paintEvent 屬性
MainWindow.show()
sys.exit(app.exec())
使用 class 的写法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import QPainter, QColor, QPen
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
# 定義 paintEvent 屬性,注意需要包含 self 和 event 參數
def paintEvent(self, event):
qpainter = QPainter()
qpainter.begin(self)
qpainter.setPen(QPen(QColor('#ff0000'),5))
qpainter.drawRect(50, 50, 100, 100)
qpainter.end()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
QPainter 常用方法说明
透过 QPainter 建立绘图器之后,就可以使用下列常用的设定方法 ( 完整方法:Qpainter Functions ):
| 方法 | 参数 | 说明 |
|---|---|---|
| begin() | 开始绘图。 | |
| end() | 结束绘图。 | |
| setPen() | QPen 或 QColor 或 style | 设定画笔。 |
| setBrush() | QBrush 或 style | 设定填充笔刷。 |
| setFont() | QFont | 设定文字。 |
常用的绘图方法:
| 方法 | 参数 | 说明 |
|---|---|---|
| drawArc() | x, y, w, h, a, alen | 绘制弧线。 |
| drawEllipse() | x, y, w, h | 绘制椭圆形。 |
| drawLine() | x1, y1, x2, y2 | 绘制直线。 |
| drawPie() | x, y, w, h, a, alen | 绘制圆饼图。 |
| drawPoint() | x, y | 绘制单一个点。 |
| drawRect() | x1, y1, w, h | 绘制矩形。 |
| drawRoundRect() | x, y, w, h, xRound=25, yRound=25 | 绘制圆角矩形。 |
| drawText() | x, y, text | 放入文字。 |
| fillRect() | x, y, w, h, color | 填满矩形。 |
| eraseRect() | x, y, w, h | 清除特定区域。 |
QPainter 放入文字
透过 QPainter 的 drawText() 方法,就能在视窗中放入文字,以下方的程序码为例,执行后视窗中间会出现红色的 hello 文字 ( 文字的颜色由 setPen() 决定 )。
from PyQt6 import QtWidgets
from PyQt6.QtGui import QPainter, QColor
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(300, 200)
def draw(self):
qpainter = QPainter()
qpainter.begin(MainWindow)
qpainter.setPen(QColor('#ff0000'))
qpainter.drawText(50,50,'hello')
qpainter.end()
MainWindow.paintEvent = draw
MainWindow.show()
sys.exit(app.exec())
class 写法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import QPainter, QColor
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
# 定義 paintEvent 屬性,注意需要包含 self 和 event 參數
def paintEvent(self, event):
self.qpainter = QPainter()
self.qpainter.begin(self)
self.qpainter.setPen(QColor('#ff0000'))
self.qpainter.drawText(50,50,'hello')
self.qpainter.end()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
如果要设定文字的样式,则可以使用 setFont() 方法搭配 QFont() 进行设定,QFont() 可以设定字体、字体大小、粗细...等样式 ( 详细参考:QFont,用法和 PyQt5 相同,但设定需改成 QFont.Style.StyleItalic ),例如下方的程序码执行后,会产生两组不同样式的文字。
from PyQt6 import QtWidgets
from PyQt6.QtGui import QPainter, QColor, QFont
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(300, 200)
def draw(self):
qpainter = QPainter()
qpainter.begin(MainWindow)
font = QFont() # 建立文字樣式物件
font.setFamily('Times') # 設定字型
font.setPointSize(50) # 設定文字大小
font.setWeight(87) # 設定文字粗細
font.setStyle(QFont.Style.StyleItalic) # 設定文字樣式
qpainter.setPen(QColor('#ff0000'))
qpainter.setFont(font) # 根據文字樣式物件設定文字樣式
qpainter.drawText(50,50,'hello') # 放入文字
qpainter.setPen(QColor('#0000ff'))
qpainter.setFont(QFont('Arial',30)) # 直接使用 QFont 設定文字樣式
qpainter.drawText(50,100,'hello') # 放入文字
qpainter.end()
MainWindow.paintEvent = draw
MainWindow.show()
sys.exit(app.exec())
使用 class 的写法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import QPainter, QColor, QFont
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
def paintEvent(self, event):
qpainter = QPainter()
qpainter.begin(self)
font = QFont()
font.setWeight(87)
font.setPointSize(50)
font.setFamily('Times')
font.setStyle(QFont.Style.StyleItalic)
qpainter.setPen(QColor('#ff0000'))
qpainter.setFont(font)
qpainter.drawText(50,50,'hello')
qpainter.setPen(QColor('#0000ff'))
qpainter.setFont(QFont('Arial',30))
qpainter.drawText(50,100,'hello')
qpainter.end()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
QPainter 绘制形状
透过 QPainter 的绘制形状方法 ( 设定 paintEvent 属性 ),就能在视窗中放入各种形状,以下方的程序码为例,执行后视窗中会出现红色正方形、绿色圆形和黑色直线。
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(300, 200)
def draw(self):
qpainter = QPainter()
qpainter.begin(MainWindow)
qpainter.setPen(QPen(QColor('#ff0000'), 5))
qpainter.drawRect(10,10,100,100)
qpainter.setPen(QPen(QColor('#00aa00'), 5))
qpainter.drawEllipse(50, 50, 100, 100)
qpainter.setPen(QPen(QColor('#000000'), 5))
qpainter.drawLine(100,100,300,200)
qpainter.end()
MainWindow.paintEvent = draw
MainWindow.show()
sys.exit(app.exec())
class 写法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import QPainter, QColor, QPen
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
def paintEvent(self, event):
self.qpainter = QPainter()
self.qpainter.begin(self)
self.qpainter.setPen(QPen(QColor('#ff0000'), 5))
self.qpainter.drawRect(10,10,100,100)
self.qpainter.setPen(QPen(QColor('#00aa00'), 5))
self.qpainter.drawEllipse(50, 50, 100, 100)
self.qpainter.setPen(QPen(QColor('#000000'), 5))
self.qpainter.drawLine(100,100,300,200)
self.qpainter.end()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
通常在绘制形状时,会搭配 QPen() 进行画笔的设定 ( 详细参考:QPen,用法和 PyQt5 相同,但是设定需改成 Qt.PenStyle.DashDotLine ),例如下方的程序码执行后,会产生三组不同样式的直线。
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(300, 200)
def draw(self):
qpainter = QPainter()
qpainter.begin(MainWindow)
qpainter.setPen(QPen(QColor('#000000'), 10))
qpainter.drawLine(50,25,250,25)
pen = QPen() # 建立畫筆樣式物件
pen.setStyle(Qt.PenStyle.DashDotLine) # 設定樣式為 Qt.DashDotLine ( Qt 在 PyQt6.QtCore 裡 )
pen.setColor(QColor('#000000')) # 設定顏色
pen.setWidth(5) # 設定粗細
qpainter.setPen(pen)
qpainter.drawLine(50,50,250,50)
pen = QPen() # 建立畫筆樣式物件
pen.setStyle(Qt.PenStyle.DotLine) # 設定樣式為 Qt.DotLine ( Qt 在 PyQt6.QtCore 裡 )
pen.setColor(QColor('#000000')) # 設定顏色
pen.setWidth(2) # 設定粗細
qpainter.setPen(pen)
qpainter.drawLine(50,75,250,75)
qpainter.end()
MainWindow.paintEvent = draw
MainWindow.show()
sys.exit(app.exec())
class 写法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
def paintEvent(self, event):
self.qpainter = QPainter()
self.qpainter.begin(self)
self.qpainter.setPen(QPen(QColor('#000000'), 10))
self.qpainter.drawLine(50,25,250,25)
self.pen = QPen() # 建立畫筆樣式物件
self.pen.setStyle(Qt.PenStyle.DashDotLine) # 設定樣式為 Qt.DashDotLine ( Qt 在 PyQt6.QtCore 裡 )
self.pen.setColor(QColor('#000000')) # 設定顏色
self.pen.setWidth(5) # 設定粗細
self.qpainter.setPen(self.pen)
self.qpainter.drawLine(50,50,250,50)
self.pen = QPen() # 建立畫筆樣式物件
self.pen.setStyle(Qt.PenStyle.DotLine) # 設定樣式為 Qt.DotLine ( Qt 在 PyQt6.QtCore 裡 )
self.pen.setColor(QColor('#000000')) # 設定顏色
self.pen.setWidth(2) # 設定粗細
self.qpainter.setPen(self.pen)
self.qpainter.drawLine(50,75,250,75)
self.qpainter.end()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
QPainter 放入图片
透过 QPainter 的 drawImage 方法,就能显示已经转换成 QImage 的图片,使用时需要搭配 QRect 指定图片的左上角座标以及长宽,下方的程序码执行后,画面里会出现一张蒙娜丽莎的画像。
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(300, 300)
def draw(self):
qpainter = QPainter()
qpainter.begin(MainWindow)
qimage = QImage('mona.jpg')
w = qimage.size().width()
h = qimage.size().height()
qpainter.drawImage(QRect(20, 20, w, h), qimage)
qpainter.end()
MainWindow.paintEvent = draw
MainWindow.show()
sys.exit(app.exec())
class 写法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 300)
def paintEvent(self, event):
self.qpainter = QPainter()
self.qpainter.begin(self)
qimage = QImage('mona.jpg')
w = qimage.size().width()
h = qimage.size().height()
self.qpainter.drawImage(QRect(20, 20, w, h), qimage)
self.qpainter.end()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
修改 QRect 的参数,就能改变放入图片的位置和大小,下方的程序码执行后,画面里会出现两张位置与大小不同的蒙娜丽莎像。
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(300, 200)
def draw(self):
qpainter = QPainter()
qpainter.begin(MainWindow)
qimage = QImage('mona.jpg')
qpainter.drawImage(QRect(0, 0, 100, 150), qimage)
qpainter.drawImage(QRect(150, 30, 150, 150), qimage)
qpainter.end()
MainWindow.paintEvent = draw
MainWindow.show()
sys.exit(app.exec())
class 写法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
def paintEvent(self, event):
self.qpainter = QPainter()
self.qpainter.begin(self)
qimage = QImage('mona.jpg')
self.qpainter.drawImage(QRect(0, 0, 100, 150), qimage)
self.qpainter.drawImage(QRect(150, 30, 150, 150), qimage)
self.qpainter.end()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
参考数据
微信扫码关注
抖音扫码关注