QPainter 繪圖 ( 儲存圖片 )
這篇教學會使用 PyQt6 的 QPainter() 搭配 QPixmap(),讓 QPainter() 所繪製的圖片可以儲存到電腦中。
快速導覽:
因為 Google Colab 不支援 PyQt6,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda )。
使用 QPainter() 搭配 QPixmap()
在「QPainter 繪圖」的教學範例中,是利用 QPainter() 物件在主視窗的背景繪圖,但許多實際的狀況並不會在主視窗的背景繪圖,而是會使用 QPixmap() 物件作為「畫布」,在畫布進行作畫,下方的程式碼執行後,會產生一個 QPixmap() 物件,在這個物件上作畫之後,再透過 QLabel() 呈現出繪圖的內容。
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)
label = QtWidgets.QLabel(MainWindow) # 建立 QLabel
label.setGeometry(0, 20, 300, 180) # 設定位置 ( 最上方留下 20px 空間 )
def draw(self):
canvas = QPixmap(300,180) # 新增 QPixmap 物件為畫布
canvas.fill(QColor('#ffdddd')) # 設定畫布背景
qpainter = QPainter() # 建立 QPainter() 物件
qpainter.begin(canvas) # 綁定 canvas 進行繪畫
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() # 繪圖結束
label.setPixmap(canvas) # 將 canvas 放入 QLabel 中
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)
self.ui()
def ui(self):
self.label = QtWidgets.QLabel(self) # 建立 QLabel
self.label.setGeometry(0, 20, 300, 180) # 設定位置 ( 最上方留下 20px 空間 )
self.canvas = QPixmap(300,180) # 新增 QPixmap 物件為畫布
self.canvas.fill(QColor('#ffdddd')) # 設定畫布背景
def paintEvent(self, event):
self.qpainter = QPainter() # 建立 QPainter() 物件
self.qpainter.begin(self.canvas) # 綁定 canvas 進行繪畫
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() # 繪圖結束
self.label.setPixmap(self.canvas) # 將 canvas 放入 QLabel 中
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
QPixmap() 儲存圖片
當作為畫布的 QPixmap() 物件已經繪製完成後,就能透過 save() 方法,將繪製的內容儲存成圖片,save() 的用法如下:
canvas = QPixmap(width, height)
canvas.save(name, fomat, quality)
修改前一段的程式碼,加入按鈕的功能,就能在點擊按鈕的當下,將 QPixmap() 物件儲存成指定格式的圖片。
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)
label = QtWidgets.QLabel(MainWindow)
label.setGeometry(0, 30, 300, 170)
def save(format):
if format == 'jpg':
label.pixmap().save('demo.jpg','JPG',90) # 儲存為 jpg
else:
label.pixmap().save('demo.png','PNG') # 儲存為 png
btn1 = QtWidgets.QPushButton(MainWindow)
btn1.setText('儲存為 jpg')
btn1.setGeometry(20,0,100,30)
btn1.clicked.connect(lambda: save('jpg')) # 綁定儲存的函式
btn2 = QtWidgets.QPushButton(MainWindow)
btn2.setText('儲存為 png')
btn2.setGeometry(120,0,100,30)
btn2.clicked.connect(lambda: save('png')) # 綁定儲存的函式
def draw(self):
canvas = QPixmap(300,170)
canvas.fill(QColor('#ffdddd'))
qpainter = QPainter()
qpainter.begin(canvas)
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()
label.setPixmap(canvas)
MainWindow.paintEvent = draw
MainWindow.show()
sys.exit(app.exec())
class 的寫法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
self.label = QtWidgets.QLabel(self)
self.label.setGeometry(0, 30, 300, 170)
self.btn1 = QtWidgets.QPushButton(self)
self.btn1.setText('儲存為 jpg')
self.btn1.setGeometry(20,0,100,30)
self.btn1.clicked.connect(lambda: self.save('jpg')) # 綁定儲存的函式
self.btn2 = QtWidgets.QPushButton(self)
self.btn2.setText('儲存為 png')
self.btn2.setGeometry(120,0,100,30)
self.btn2.clicked.connect(lambda: self.save('png')) # 綁定儲存的函式
def save(self, format):
if format == 'jpg':
self.label.pixmap().save('demo.jpg','JPG',90) # 儲存為 jpg
else:
self.label.pixmap().save('demo.png','PNG') # 儲存為 png
def paintEvent(self, event):
canvas = QPixmap(300,170)
canvas.fill(QColor('#ffdddd'))
qpainter = QPainter()
qpainter.begin(canvas)
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()
self.label.setPixmap(canvas)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~