Skip to content

[PyQt5] 把 QLabel 元件中的文字、圖像儲存成圖片的方法筆記

在使用 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 的轉換成為圖片。

Leave a Reply