QLabelでの画像のリサイズ方法
QPixmapで画像を開きQLabel上に画像を貼り付けるというのはよくやると思います。
QLabelのサイズを超える画像をQPixmapで開いた場合はリサイズする必要がありますよね。
そんなとき、下のツイートの問題が発生しました。
今日ハマったこと
— yam (@yamamon_Lab) 2020年4月1日
QPixmap::scaled()は戻り値を使う
scaled呼び出したインスタンスがリサイズされると勘違いしてて小一時間ムダにした…
リサイズにハマったので、対処法を記載します。
(ツイートに答え書いてるけどね・・・)
環境:python3.6.8, PyQt5
関連するリファレンスは以下です。
QPixmap:QPixmap Class | Qt GUI 5.15.0
ダメなコード
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout from PyQt5.QtGui import QPixmap class ImageViewer(QWidget): def __init__(self): super().__init__() self.width = 512 self.height = 512 self._init_ui() def _init_ui(self): self.resize(self.width,self.height) layout = QVBoxLayout() self.title = QLabel() self.image = QLabel() layout.addWidget(self.image) self.setLayout(layout) pixmap = QPixmap('test.png') pixmap.scaled(self.width,self.height,Qt.KeepAspectRatio,Qt.FastTransformation) self.image.setPixmap(pixmap) self.show() if __name__ == '__main__': app = QApplication(sys.argv) widget = ImageViewer() sys.exit(app.exec_())
このコードを実行すると512 x 512を超えるサイズの画像を表示するとウインドウが広がってしまいます。
正しく動くコード
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout from PyQt5.QtGui import QPixmap class ImageViewer(QWidget): def __init__(self): super().__init__() self.width = 512 self.height = 512 self._init_ui() def _init_ui(self): self.resize(self.width,self.height) layout = QVBoxLayout() self.title = QLabel() self.image = QLabel() layout.addWidget(self.image) self.setLayout(layout) pixmap = QPixmap('test.png') pixmap = pixmap.scaled(self.width,self.height,Qt.KeepAspectRatio,Qt.FastTransformation) self.image.setPixmap(pixmap) self.show() if __name__ == '__main__': app = QApplication(sys.argv) widget = ImageViewer() sys.exit(app.exec_())
このコードを実行すると512 x 512を超えるサイズの画像を表示してもウインドウは512 x 512で固定となります。
何がいけなかったのか?
全てはQPixmapの仕様に対する私の勘違いに原因がありました。
ミソになるのは下の一文です。
pixmap = pixmap.scaled(self.width,self.height,Qt.KeepAspectRatio,Qt.FastTransformation)
QPixmapにはscaled()というメソッドがあり、このメソッドを使用することでリサイズできます。
私はscaled()を呼び出した、QPixmapのインスタンスがそのままリサイズされると考えていました。
(↑referenceよく読め・・・)
しかし実際は、scaled()の戻り値のQPixmapの変数にリサイズ後のデータが格納され、scaled()を呼び出したインスタンスは何も変化していません。
ダメな例では scaled() を呼び出した後もそのインスタンスを使い続けていたため画像が正しくリサイズされませんでした。
皆さんもお気をつけください。