Last Updated on 2021-05-17 by Clay
在使用 PyQt5 開發界面的時候,我不知道究竟會有多少時候,我們可能會用到 QLabel 這個元件來儲存成圖片。如果是一般我們用來『顯示圖片』的 QLabel,那麼只要轉成 PIL 格式儲存即可,可說是相當簡單。
今天我在開發程式的時候,剛好遇到我需要『擷取』整個 QLabel 儲存成圖片。這是個有點奇怪的需求, 我找遍網路基本上沒瞧見是否有人有這樣的步驟說明。(當然,我覺得有可能是我根本沒下對關鍵字)
卡在這個『將 Label 儲存成圖片』的過程卡了快要兩個小時,這才終於摸索出方法。故此,我認為這一定要紀錄下來,說不準將來有誰跟我會有一樣的問題呢。
將 QLabel 的圖片存檔
這個倒沒什麼難的,使用 PIL 模組便可順利儲存。
# -*- coding: utf-8 -*- import sys from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PIL import ImageQt class MainWindow(QWidget): def __init__(self): super(MainWindow, self).__init__() self.resize(800, 600) self.setWindowTitle('Painter Board') self.label = QLabel(self) self.label.setGeometry(0, 0, 800, 600) self.label.setPixmap(QPixmap("../../Pictures/Saved Pictures/dog.jpg")) self.label.setScaledContents(True) self.add = QShortcut(QKeySequence("Ctrl+S"), self) self.add.activated.connect(self.compositeEvent) def compositeEvent(self): image = ImageQt.fromqpixmap(self.label.pixmap()) image.save('test.png') if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() sys.exit(app.exec_())
Output:
以上是簡單的使用 QLabel 將我們想要的圖片顯示的功能。如果對 PyQt5 這方面的指令有興趣,可以參考我之前寫過的《PyQt5 基本教學 (3) QMainWindow, QIcon, QPixmap, QPalette》。
然後我們按下 Ctrl + S,根據我快捷鍵設定的函式,我會使用 PIL 當中的 ImageQt 將該 Label 的 Pixmap 讀出,並儲存成『test.png』。
我們試著在外面打開 test.png 這個檔案:
看起來是相當正常的。我們可以依此順利將圖片儲存起來。
將 QLabel 的文字儲存成圖片
接下來就是比較難找到答案的部份了。首先,我們取消剛剛使用 QPixmap 顯示圖片的 QLabel,改成顯示文字。
# -*- coding: utf-8 -*- import sys from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PIL import ImageQt class MainWindow(QWidget): def __init__(self): super(MainWindow, self).__init__() self.resize(800, 600) self.setWindowTitle('Painter Board') self.label = QLabel(self) self.label.setGeometry(0, 0, 800, 600) self.label.setText('Good day!') self.add = QShortcut(QKeySequence("Ctrl+S"), self) self.add.activated.connect(self.compositeEvent) def compositeEvent(self): image = ImageQt.fromqpixmap(self.label.pixmap()) image.save('test.png') if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() sys.exit(app.exec_())
Output:
就像這樣。然後我們再按一次 Ctrl + S 存檔,這時候我們會觸發報錯:
AttributeError: 'NoneType' object has no attribute 'hasAlphaChannel'
很顯然,顯示文字的 QLabel 根本不適用這樣的儲存方式。
最後,找不到網路上解答的我,摸索了兩個小時終於找到辦法了。
將儲存圖片的這行程式碼:
image = ImageQt.fromqpixmap(self.label.pixmap())
更改為:
image = ImageQt.fromqpixmap(self.label.grab())
然後就可以正常存檔了。
後記
會遇到這個問題,其實是因為我正在把 QLabel 當成繪圖板的元件。關於這項工作的處理,也許你可以參考一下我寫的《Python 中使用 PyQt5 製作簡易繪圖板》,應該就明白我想要做什麼。
值得一提的是,當我把 QLabel 重寫、繼承成為繪圖板之後,使用 grab() 一樣可以通過 PIL 的轉換成為圖片。