今回は Python の tkinter を利用して「マウスホイールで画像のリサイズ」を行うアプリを開発していきたいと思います。
このアプリを開発することで、単に GUI に対する処理だけでなく、画像のリサイズに関する知識も身につけることができます!
Contents
開発するアプリ
まずは開発するアプリを簡単に紹介します。
アプリの画面
アプリの画面は下の図のようになります。
メインウィンドウの中にキャンバスウィジェットが1つあり、このキャンバスウィジェット上に画像を描画しているだけです。
スポンサーリンク
アプリの操作
アプリが受け付ける操作はマウスホイール操作のみです。
ノートパソコンを利用されている&マウスが無い方であれば、トラックパッドで指2本のスワイプで同様の操作を行うことが可能です。
マウスホイールでスクロールアップすると(トラックパッドでスクロールアップすると)、表示されている画像が拡大されて表示されます。
逆にマウスホイールでスクロールダウンすると(トラックパッドでスクロールダウンすると)、表示されている画像が縮小されて表示されます。
マウスホイールを上 or 下のどちらに動かせばスクロールアップ(画面が上方向にスクロール) or スクロール(画面が下方向にスクロール)のどちらが行われるかは環境や設定によって異なるようです
私の環境(MacOS)だと、トラックパッドやマウスホイールを上方向に動かすとスクロールダウンし、下方向に動かすとスクロールアップしますが、環境によっては逆の場合もあります
アプリの作り方
それでは先ほど紹介したアプリの作り方のポイントを解説していきたいと思います。
アプリの処理の全体的な流れ
まずはアプリの処理の全体的な流れについて簡単に解説しておきます。
最初に、アプリは起動時に下記の処理を行います。
- 画像を読み込む
- ウィジェットを作成・配置する
- マウスホイール操作イベントを受け付ける
- キャンバスサイズに合わせて画像をリサイズする
- 画像をキャンバスに描画する
さらに、ユーザーからのマウスホイール操作によって下記の処理を行います。
- マウスホイール操作の情報を取得する
- 拡大率を計算する
- 画像をリサイズする
- 画像をキャンバスに描画する
ここからはこれらの処理の流れを実現するためのポイント部分のみを解説していきます。
スポンサーリンク
ウィジェットを作成・配置する
まずはウィジェットの作成・配置を行ってアプリの見た目を開発します。
といっても今回使用するウィジェットは、(メインウィンドウを除けば)キャンバスのみになります。
マウスホイール操作を受け付ける
次に必要なのはマウスホイール操作の受付です。
tkinter ではマウスホイール操作もイベントとして受け付けることが可能で、この操作に対してイベント処理を設定することが可能です。
イベントに関しては下記ページで解説していますので、詳しく知りたい方は是非こちらのページも読んでみてください。
Tkinterの使い方:イベント処理を行うマウスホイール操作に対してイベント処理を設定するためには、"<MouseWheel>"
をイベントシーケンスとして下記のように bind
メソッドをすればOKです。
# self.canvasはCanvasクラスのインスタンス
self.canvas.bind("<MouseWheel>", self.event_handler)
bind
メソッドを実行したオブジェクトに対してイベント処理が設定されますので、キャンバス上でのマウスホイール操作が行われた際に event_handler
関数が実行されるようになります。
OS が Linux の場合はイベントシーケンスを "<MouseWheel>"
ではなく "<ButtonPress-4>"
と "<ButtonPress-5>"
に設定するとマウスホイールのイベントが受け付けられるようです
前者はスクロールアップ、後者はスクロールダウンのイベントに対するイベントシーケンスになります
おそらく下記でマウスホイールの設定を受け付けることができるようになると思います。
# self.canvasはCanvasクラスのインスタンス
self.canvas.bind("<ButtonPress-4>", self.event_handler)
self.canvas.bind("<ButtonPress-5>", self.event_handler)
マウスホイール操作の情報取得
このアプリのメイン機能は「マウスホイール操作により画像のリサイズを行う」です。
マウスホイール操作によりスクロールアップが行われた際には画像の拡大を行い、マウスホイール操作によりスクロールダウンが行われた際には画像の縮小を行います。
さらに、マウスホイール操作で何ステップ分マウスホイールが動かされたかに応じて拡大率・縮小率の大小を決定します。
この辺りの処理を実現するためには、マウスホイールによりスクロールアップとスクロールダウンのどちらが行われたかや、どれくらいマウスホイールが動かされたかの情報が必要ですので、まずはこれらの情報の取得方法について解説していきたいと思います。
マウスホイール操作の情報取得
マウスホイールによりスクロールアップとスクロールダウンのどちらが行われたかや、どれくらいマウスホイールが動かされたかの情報は、tkinter.Event
クラスの delta
属性により取得することができます。
前述の bind
メソッドで設定したイベントハンドラ(イベント発生時に実行される関数・メソッド)では、実行時に引数として tkinter.Event
クラスのオブジェクトが渡されます。
ですので、 イベントハンドラ内で、このオブジェクトの delta
属性を参照することで、スクロールアップ or スクロールダウンのどちらが行われたかやどれくらいマウスホイールが動かされたかの情報を取得できます。
delta
の値の意味
この delta
には整数の値が格納されています。
この値はマウス操作によりスクロールアップ or スクロールダウンがされたか、どれくらいマウスホイールが動かされたかに基づいて設定されます。
- プラスの値:スクロールアップされた
- マイナスの値:スクロールダウンされた
- 値の絶対値:マウスホイールが動かされた量
マウスホイールによりスクロールアップされた場合は delta
に正の値が、スクロールダウンされた場合は delta
に負の値が格納されます。
実際に delta
の値はマウスホイールを動かした量に応じて設定されます。
MacOS の場合、マウスホイールを1ステップ分動かすと delta
に ±1 の値が格納されます。マウスホイールを強く動かすと複数ステップ分マウスホイールが動かされたことになり、絶対値として大きな値が delta
に格納されることになります。
Windows の場合は delta
には 120 の倍数が格納されるようです
私は Windows を使っていないのではっきりとは分からないですが、おそらくマウスホイールを動かしたステップ数分 x 120 の値が格納されます
スポンサーリンク
拡大率を算出する
続いて、ここまで説明してきた delta
の値から実際にリサイズを行うときの拡大率を求めていきます。
今回紹介するスクリプトでは下記のように拡大率を決定しています。
# eventはEventクラスのインスタンス
self.ratio = self.ratio * (100 + event.delta) / 100
self.ratio
には、前回キャンバスに描画するために画像をリサイズした時に用いた拡大率が格納されています。
この self.ratio
をマウスホイール操作イベント発生時に上記処理により event.delta
の値に基づいて新たな拡大率に更新しています。
この更新後の self.ratio
を拡大率として画像をリサイズしてやれば、マウスホイール操作が行われるたびに、マウスホイール操作の情報に応じて画像のリサイズを行うことができます。
上記の計算では、event.delta
がプラスの値の場合は、もともとの self.ratio
よりも大きな値に、event.delta
がマイナスの値の場合は、もともとの self.ratio
よりも小さな値に更新されるようになっているため、スクロールアップをすれば画像がより大きく、スクロールダウンすれば画像がより小さくリサイズされるような拡大率(self.ratio
)に更新することができます。
上記の計算式は Mac で動作していることを想定して作成しています
前述の通り Windows の場合は delta
の値が 120 の倍数になるようですので、下記のように計算すればもしかしたら上手く動くかもしれません
# eventはEventクラスのインスタンス self.ratio = self.ratio * (100 + (event.delta / 120)) / 100
画像処理を行う
今回は画像の拡大縮小(リサイズ)を行う必要がありますので、画像を取り扱う際には PIL の Image モジュールを利用しようと思います。
画像の読み込み
画像の読み込みには PIL の Image モジュールに用意された open
関数を利用します。
from PIL import Image
# IMAGE_PATHは読み込みたい画像ファイルへのパス
self.image = Image.open(IMAGE_PATH)
画像のリサイズ
画像のリサイズには resize
メソッドを利用します。
from PIL import Image
# self.imageはPIL Imageクラスのインスタンス
self.draw_image = self.image.resize(
(resized_width, resized_height),
Image.BILINEAR
)
resize
メソッドの引数の詳細は下記の通りです。
- 第1引数:リサイズ後の画像サイズ
- 第2引数:リサイズ時に使用するフィルター
resize
メソッドの第1引数では、リサイズ後の画像の幅と高さをタプル形式で指定します。
リサイズ後の画像の幅や高さは拡大率を算出するで求めた self.ratio
を用いて計算します。
PIL 画像オブジェクトでは、width
メンバと height
メンバから幅と高さを取得することができますので、それそれぞに拡大率 self.ratio
を掛けてやれば、リサイズ後の幅と高さを計算することができます。
# self.imageはPIL画像オブジェクト
resized_width = self.image.width * self.ratio
resized_height = self.image.height * self.ratio
resize
メソッドの第2引数のフィルターとしては指定可能な値の一例は下記になります。
Image.NEAREST
Image.BILINEAR
Image.LANCZOS
使用するフィルターによってリサイズ後の画像の画質やリサイズ時の処理時間が変わります。フィルターの詳細は下記ページから確認することが可能です。
https://pillow.readthedocs.io/en/4.0.x/handbook/concepts.html#filters
tkinter 画像への変換
PIL で読み込んだ画像や画像処理した関数はそのままでは tkinter のキャンバスには描画できません。
そのため、キャンバスに描画する前に PIL の画像を tkinter 用の画像に変換を行います。
この辺りの変換については下記ページで解説していますので、詳しく知りたい方は是非こちらのページも読んでみてください。
【Python】PIL ⇔ OpenCV2 ⇔ Tkinter 画像オブジェクトの相互変換要は、下記の ImageTk モジュール PhotoImage
クラスのコンストラクタを実行することで PIL の画像を tkinter 用の画像に変換することができます。
from PIL import Image, ImageTk
# self.imageはPIL Imageクラスのインスタンス
self.tk_image = ImageTk.PhotoImage(self.image)
変換後の画像をキャンバスへの画像描画メソッドである create_image
の引数 image
に指定してやれば、キャンバスに画像を描画することができます。
アプリのスクリプト
ではここまで解説してきたアプリのサンプルスクリプトや動作を紹介していきたいと思います。
スポンサーリンク
アプリのサンプルスクリプト
アプリのサンプルスクリプトは下記のようになります。
import tkinter
from PIL import Image, ImageTk
import time
import math
# 読み込む画像へのファイルパス設定
IMAGE_PATH = "cat.jpg"
# キャンバスのサイズ設定
CANVAS_WIDTH = 600
CANVAS_HEIGHT = 400
class ImageZoom():
'''画像拡大縮小アプリ'''
def __init__(self, master):
self.master = master
# 画像の読み込み
self.image = Image.open(IMAGE_PATH)
# キャンバスのサイズ設定
self.canvas_width, self.canvas_height = CANVAS_WIDTH, CANVAS_HEIGHT
# 表示する画像の設定
self.draw_image = self.image
self.tk_image = None
# ウィジェットの作成と配置
self.create_widgets()
# イベント設定
self.set_events()
# キャンバスサイズに合わせて画像の拡大率決定
self.ratio = min(
self.canvas_width / self.image.width,
self.canvas_height / self.image.height
)
# 画像の表示
self.resize(self.ratio)
# 画像の描画
self.draw()
def create_widgets(self):
'''ウィジェットを作成する'''
# キャンバス作成
self.canvas = tkinter.Canvas(
self.master,
width = self.canvas_width,
height = self.canvas_height,
highlightthickness=0
)
self.canvas.pack()
def draw(self):
'''キャンバスの中心に画像を描画する'''
# tkinter画像オブジェクトに変換
self.tk_image = ImageTk.PhotoImage(self.draw_image)
# キャンバスに画像を描画
self.canvas.create_image(
self.canvas_width // 2, self.canvas_height // 2,
anchor=tkinter.CENTER,
image=self.tk_image
)
def set_events(self):
'''イベントの設定を行う'''
# マウスホイールイベントを設定
self.canvas.bind("<MouseWheel>", self.event_handler)
def event_handler(self, event):
'''マウスホイールイベント発生時の処理'''
# マウスホイール(トラックパッド)の動きに合わせて拡大率設定
self.ratio = self.ratio * (100 + event.delta) / 100
# 拡大率の下限と上限を設定
if self.ratio < 0.01:
self.ratio = 0.01
if self.ratio > 100:
self.ratio = 100
# リサイズ
self.resize(self.ratio)
# 画像の描画
self.draw()
def resize(self, ratio):
'''画像のリサイズを行う'''
start = time.time()
# リサイズ後画像サイズを算出
resized_width = self.image.width * self.ratio
resized_height = self.image.height * self.ratio
# リサイズ後画像サイズが0の場合は1に設定
if resized_width < 1:
resized_width = 1
if resized_height < 1:
resized_height = 1
# 画像をリサイズ
self.draw_image = self.image.resize(
(int(resized_width), int(resized_height)),
Image.BILINEAR
)
end = time.time()
print("拡大率" + str(self.ratio) + "のリサイズ時間:" + str(end - start))
app = tkinter.Tk()
iz = ImageZoom(app)
app.mainloop()
アプリの設定
スクリプトの先頭付近でアプリの設定を行うことができるようにしています。
# 読み込む画像へのファイルパス設定
IMAGE_PATH = "neko_before.jpg"
# キャンバスのサイズ設定
CANVAS_WIDTH = 600
CANVAS_HEIGHT = 400
IMAGE_PATH
に指定するファイルパスの設定により、アプリに表示する画像を変更することができます。
CANVAS_WIDTH
と CANVAS_HEIGHT
ではキャンバスのサイズを設定することができます。大きすぎるとアプリが重くなるので注意してください。
アプリの動作確認
スクリプトを実行するとアプリが起動し、IMAGE_PATH
に指定した画像が表示されます。画像上でマウスホイールを上下に動かしたり、トラックパッドに対して指2本でスワイプすることで画像がリサイズされます。
ただし、かなり処理が重くて画像の表示がゆっくりマウスホイールを動かすことをオススメします。
スポンサーリンク
アプリの動きを滑らかにする改善
先ほど紹介したスクリプトでは画像の表示がかなりカクつきます。特にスクロールアップして画像サイズが大きくなりすぎると、このカクつきが顕著に発生します。
ここからは、このカクつきの原因と対策について解説していきたいと思います。
リサイズ処理が重い
原因の一つ目はリサイズ処理が重い(時間がかかる)ことです。
原因
一般的にリサイズ処理は、リサイズ後画像のサイズが大きいほど重くなります。
マウスホイール操作を受け付けるたびにリサイズを行うようにしていますので、リサイズに処理に時間がかかると、マウスホイール操作が連続して行われた時に処理が追いつかなくなってしまい、アプリがカクつきます。
解決方法
ポイントは、キャンバスからはみ出る画像部分は表示されないが、リサイズ処理はキャンバスからはみ出る部分にも行われている点です。
キャンバスからはみ出る部分は表示されないのでリサイズしても意味がありません。その分無駄な処理が発生して時間がかかるだけです。
なので、キャンバスに表示される部分のみをリサイズしてやれば良いです。これにより、リサイズ後の画像サイズが基本的にキャンバスサイズ以下になります(誤差などあるので実際にはならない場合もある)。
リサイズ後の画像サイズが小さくなるので、その分処理時間が短くなり、アプリのカクつきを抑えることができます。
これは、リサイズによりキャンバスからはみ出ると判断した部分はリサイズ処理前にクロップしてやり、残った部分のみをリサイズするようにすることで実現することができます。
リサイズの前にクロップ処理を行うようにした resize
メソッドが下記になります。
def resize(self, ratio):
'''画像のリサイズを行う'''
start = time.time()
# リサイズ後画像サイズを算出
resized_width = self.image.width * self.ratio
resized_height = self.image.height * self.ratio
# リサイズ後画像サイズが0の場合は1に設定
if resized_width < 1:
resized_width = 1
if resized_height < 1:
resized_height = 1
# クロップする領域を決定していく
sx = 0
sy = 0
ex = resized_width - 1
ey = resized_height - 1
if resized_width > self.canvas_width:
# はみ出る場合はリサイズ後にキャンバスからはみ出ないようにリサイズ前にクロップ
sx = (resized_width - self.canvas_width) / 2
ex = sx + self.canvas_width
if resized_height > self.canvas_height:
# はみ出る場合はリサイズ後にキャンバスからはみ出ないようにリサイズ前にクロップ
sy = (resized_height - self.canvas_height) / 2
ey = sy + self.canvas_height
# リサイズ後後にキャンバスからはみ出ない領域の矩形を設定
crop_size = (
math.floor(sx / self.ratio),
math.floor(sy / self.ratio),
math.ceil(ex / self.ratio),
math.ceil(ey / self.ratio)
)
# クロップ
crop_image = self.image.crop(crop_size)
# キャンバスに描画する画像のサイズを設定
draw_width = int(self.ratio * crop_image.width)
draw_height = int(self.ratio * crop_image.height)
# 画像をリサイズ
self.draw_image = crop_image.resize(
(draw_width, draw_height),
Image.BILINEAR
)
end = time.time()
print("拡大率" + str(self.ratio) + "のリサイズ時間:" + str(end - start))
リサイズ後画像がキャンバスサイズよりも極力大きくならないようにクロップを行うようにしたことで、アプリのカクつきを抑えることができます。
上記スクリプトではリサイズにかかる時間を表示するようにしていますので、クロップを行う例と行わない例を比較してみると時間の違いが分かり易いと思います。
mainloop
に戻らない
おそらくクロップ処理を追加することでアプリのカクつきはかなり抑えられるのではないかと思います。
ただしマウスホイール操作を素早く連続で行った場合はまだカクつくと思います。
次はマウスホイール操作を連続で行った場合もカクつかないように改善していきたいと思います。
原因
下記ページで解説しているように、tkinter でのウィジェットへの設定反映やキャンバスでの図形・画像の描画は mainloop
の中で行われます。
要は create_image
メソッドでキャンバスに画像を描画しても即座には画面には反映されず、mainloop
に処理が戻ったときに画面に反映されるということです。
一方で、イベントハンドラ内での処理が終わらないと mainloop
には処理が戻りません(アプリが暇にならないと mainloop
に戻らない)。
先程紹介したスクリプトでは、イベントハンドラでリサイズを実行しているので、リサイズが終わらないと mainloop
に処理が戻らず、画像の描画が行われないことになります。
さらにマウスホイール操作が行われるたびにイベントハンドラが実行されるようにしているため、素早くマウスホイール操作が行われると連続してリサイズが実行され、それらのリサイズが全て終了しないと画像の描画(の画面への反映)は行われません。
イメージとしては下の図のように画面更新が遅れます。
つまり、マウスホイール操作が素早く連続で行われるとリサイズ処理が連続で実行されてしまい、その間キャンバスの画像が更新されないのでアプリがカクついているやように見えるというわけです。
解決策
これはとにかく mainloop
に処理を戻すことを意識してプログラミングしてやれば解決できます。
より具体的に言うと、リサイズ処理後は(マウスホイール操作の)イベント受付を一定時間停止します。
event_handler
メソッドを下記のように変更することで、リサイズ処理後のイベント受付を一定時間(10 ms)停止することができます。
def event_handler(self, event):
'''マウスホイールイベント発生時の処理'''
# マウスホイール(トラックパッド)の動きに合わせて拡大率設定
self.ratio = self.ratio * (100 + event.delta) / 100
# 拡大率の下限と上限を設定
if self.ratio < 0.01:
self.ratio = 0.01
if self.ratio > 100:
self.ratio = 100
# リサイズ
self.resize(self.ratio)
# 画像の描画
self.draw()
# 一旦イベント受付終了
self.unset_events()
# 少しディレイを入れてイベント再受付
self.master.after(10, self.set_events)
unset_events
はイベント受付を終了するメソッドです。詳細は最後に載せている改善後のスクリプトを参照してください。
これにより、リサイズ処理の後は必ず mainloop
に処理が戻るようになります。
これにより、連続してリサイズ処理が実行されて画像の描画が遅れることが無くなるので、アプリの動きとしてカクつきを防ぐことができます。
リサイズ中のマウスホイール操作が受け付けられなくなるので操作性が下がりそうですが、キャンバスのサイズがそこまで多くなければリサイズの時間も短いので、操作性にあまり影響は無いと思います。
アプリがカクつく時と比較すると、おそらくほとんどの方が上記でイベント受付を中止した時の方が使用感が良いと感じるのではないかと思います。
スポンサーリンク
改善後のスクリプト
改善後のスクリプト全体は下記のようになります。
import tkinter
from PIL import Image, ImageTk
import time
import math
# 読み込む画像へのファイルパス設定
IMAGE_PATH = "cat.jpg"
# キャンバスのサイズ設定
CANVAS_WIDTH = 600
CANVAS_HEIGHT = 400
class ImageZoom():
'''画像拡大縮小アプリ'''
def __init__(self, master):
self.master = master
# 画像の読み込み
self.image = Image.open(IMAGE_PATH)
# キャンバスのサイズ設定
self.canvas_width, self.canvas_height = CANVAS_WIDTH, CANVAS_HEIGHT
# 表示する画像の設定
self.draw_image = None
self.tk_image = None
# ウィジェットの作成と配置
self.create_widgets()
# イベント設定
self.set_events()
# キャンバスサイズに合わせて画像の拡大率決定
self.ratio = min(
self.canvas_width / self.image.width,
self.canvas_height / self.image.height
)
# 画像の表示
self.resize(self.ratio)
# 画像の描画
self.draw()
def create_widgets(self):
'''ウィジェットを作成する'''
# キャンバス作成
self.canvas = tkinter.Canvas(
self.master,
width = self.canvas_width,
height = self.canvas_height,
highlightthickness=0
)
self.canvas.pack()
def draw(self):
'''キャンバスの中心に画像を描画する'''
# tkinter画像オブジェクトに変換
self.tk_image = ImageTk.PhotoImage(self.draw_image)
# キャンバスに画像を描画
self.canvas.create_image(
self.canvas_width // 2, self.canvas_height // 2,
anchor=tkinter.CENTER,
image=self.tk_image
)
def set_events(self):
'''イベントの設定を行う'''
# マウスホイールイベントを設定
self.canvas.bind("<MouseWheel>", self.event_handler)
# Linux の場合は下記で設定できる?
# self.canvas.bind("<ButtonPress-4>", self.event_handler)
# self.canvas.bind("<ButtonPress-5>", self.event_handler)
def unset_events(self):
'''イベント設定の取り消し'''
# マウスホイールイベント取り消し
self.canvas.unbind("<MouseWheel>")
# Linux の場合は下記で取り消しできる?
# self.canvas.bind("<ButtonPress-4>"
# self.canvas.bind("<ButtonPress-5>")
def event_handler(self, event):
'''マウスホイールイベント発生時の処理'''
# マウスホイール(トラックパッド)の動きに合わせて拡大率設定
self.ratio = self.ratio * (100 + event.delta) / 100
# 拡大率の下限と上限を設定
if self.ratio < 0.01:
self.ratio = 0.01
if self.ratio > 100:
self.ratio = 100
# リサイズ
self.resize(self.ratio)
# 画像の描画
self.draw()
# 一旦イベント受付終了
self.unset_events()
# 少しディレイを入れてイベント再受付
self.master.after(10, self.set_events)
def resize(self, ratio):
'''画像のリサイズを行う'''
start = time.time()
# リサイズ後画像サイズを算出
resized_width = self.image.width * self.ratio
resized_height = self.image.height * self.ratio
# リサイズ後画像サイズが0の場合は1に設定
if resized_width < 1:
resized_width = 1
if resized_height < 1:
resized_height = 1
# クロップする領域を決定していく
sx = 0
sy = 0
ex = resized_width - 1
ey = resized_height - 1
if resized_width > self.canvas_width:
# はみ出る場合はリサイズ後にキャンバスからはみ出ないようにリサイズ前にクロップ
sx = (resized_width - self.canvas_width) / 2
ex = sx + self.canvas_width
if resized_height > self.canvas_height:
# はみ出る場合はリサイズ後にキャンバスからはみ出ないようにリサイズ前にクロップ
sy = (resized_height - self.canvas_height) / 2
ey = sy + self.canvas_height
# リサイズ後後にキャンバスからはみ出ない領域の矩形を設定
crop_size = (
math.floor(sx / self.ratio),
math.floor(sy / self.ratio),
math.ceil(ex / self.ratio),
math.ceil(ey / self.ratio)
)
# クロップ
crop_image = self.image.crop(crop_size)
# キャンバスに描画する画像のサイズを設定
draw_width = int(self.ratio * crop_image.width)
draw_height = int(self.ratio * crop_image.height)
# 画像をリサイズ
self.draw_image = crop_image.resize(
(draw_width, draw_height),
Image.BILINEAR
)
end = time.time()
print("拡大率" + str(self.ratio) + "のリサイズ時間:" + str(end - start))
def main():
app = tkinter.Tk()
iz = ImageZoom(app)
app.mainloop()
main()
動作させると、改善前のスクリプトに比べてサクサク画像のリサイズが行われるようになったことが確認できると思います。
まとめ
このページでは、Python の tkinter で、マウスホイール操作(トラックパッド操作)により画像をリサイズする方法について解説しました。
tkinter ではさまざまなイベントを受け付けることが可能であり、このマウスホイール操作イベントはその一例です。
ユーザーの操作を受け付けるためにはイベント処理の知識は必須ですので、是非理解しておきましょう!
Tkinterの使い方:イベント処理を行うまた今回は画像処理やアプリの処理を軽くする方法についても解説しました!
PIL 等の高度な画像処理が行えるライブラリで作成したオブジェクトは、そのままでは tkinter で表示できないので注意しましょう。下記ページで解説しているように変換が必要です。
【Python】PIL ⇔ OpenCV2 ⇔ Tkinter 画像オブジェクトの相互変換さらに、スクリプトを改善する時に出てきた mainloop
もイベントを扱う上で非常に重要な関数になります。
しっかり理解しておくと、よりユーザーが操作しやすいアプリを開発しやすくなります。
mainloop
については下記ページで解説していますので、是非こちらのページも読んでみていただければと思います!