yam’s Lab

ハマったこと、学んだことを備忘録として記事にします。主にC++,Qt,ROS,Pythonについて取り扱います。

QLabelでの画像のリサイズ方法

QPixmapで画像を開きQLabel上に画像を貼り付けるというのはよくやると思います。
QLabelのサイズを超える画像をQPixmapで開いた場合はリサイズする必要がありますよね。

そんなとき、下のツイートの問題が発生しました。


リサイズにハマったので、対処法を記載します。
(ツイートに答え書いてるけどね・・・)

環境: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() を呼び出した後もそのインスタンスを使い続けていたため画像が正しくリサイズされませんでした。

皆さんもお気をつけください。