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())
參考資料
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~