2022/04/08(金) [n年前の日記]
#1 [python] tkinterのCanvas.scaleについて調べてた
Python + tkinter のキャンバス(Canvas)についてググってたら .scale() というメソッドがあると知って、もしやそのメソッドを使えばキャンバスの拡大縮小が簡単にできるのだろうかと気になってきた。巷の解説ページには「図形や画像を拡大縮小できる」と書いてあったりもするようだし…。画像も拡大縮小してくれるならありがたいのだけど、さてはて…。
そんなわけで、試してみた。動作確認環境は以下。
_05_canvas_scale.py
使用画像は以下。
_lena_std.png
py 05_canvas_scale.py で実行。
うすうす予想はしていたけれど、画像は拡大縮小しないやん…。図形だけやん…。まあ、.scale() が画像も拡大縮小してくれるメソッドなら、皆 Pillow を使わずにコレで処理しているはずだけど、しかしそうではないわけで…。巷の解説ページは、自分でスクリプトを書いて動作確認をせずに、画像も変化するものと思い込んで紹介しているのだろうな…。
さておき。キャンバスに対して描画された、矩形、ポリゴン、楕円等は、たしかに拡大縮小しているように見える。線の太さは変わってないけれど、そこは変化しないほうが都合がいいのだろう…。あくまで、各図形の座標情報だけが拡大縮小される、と捉えればいいのだろうか。
そんなわけで、試してみた。動作確認環境は以下。
- Windows10 x64 21H2 + Python 3.9.12 64bit + Pillow 9.1.0
- Windows10 x64 21H2 + Python 2.7.18 32bit + Pillow 6.2.2
_05_canvas_scale.py
try:
# Python 3.x
import tkinter as tk
except Exception:
# Python 2.7
import Tkinter as tk
from PIL import Image, ImageTk
class App(tk.Frame, object):
"""My App."""
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.master.title("Canvas sample")
self.master.geometry("600x600")
self.frm = tk.Frame(self.master)
self.frm.pack(expand=1, fill=tk.BOTH)
self.frm.rowconfigure(1, weight=1)
self.frm.columnconfigure(0, weight=1)
# create Button, Label
self.bfrm = tk.Frame(self.frm)
self.bfrm.grid(row=0, column=0, sticky=tk.W + tk.E)
self.btn0 = tk.Button(self.bfrm, text="-", command=lambda: self.dec_ratio())
self.btn1 = tk.Button(self.bfrm, text="+", command=lambda: self.inc_ratio())
self.lblstr = tk.StringVar()
self.lblstr.set("100%")
self.lbl = tk.Label(self.bfrm, textvariable=self.lblstr)
self.btn0.pack(side=tk.LEFT, ipadx=8, padx=4)
self.btn1.pack(side=tk.LEFT, ipadx=8, padx=4)
self.lbl.pack(side=tk.LEFT, ipadx=8, padx=8)
# create Canvas
self.canvas = tk.Canvas(self.frm, bg="#666666")
self.canvas.grid(row=1, column=0, sticky=tk.N + tk.S + tk.W + tk.E)
# load image
self.im = Image.open("lena_std.png")
self.photo_image = ImageTk.PhotoImage(image=self.im)
self.now_ratio = 1.0
self.tgt_ratio = 1.0
self.update()
cw = self.canvas.winfo_width()
ch = self.canvas.winfo_height()
# draw image
self.canvas.create_image(cw / 2, ch / 2, image=self.photo_image)
# darw Rectangle, Oval, Polygon
x = cw / 2
y = ch / 2
self.canvas.create_rectangle(x, y, x + 24, y + 96, width=4, outline="#ff0000")
self.canvas.create_oval(x + 32, y + 32, x - 32, y - 32, width=6, outline="#00ff00")
self.canvas.create_polygon(x, y, x - 40, y - 60, x - 80, y + 30,
width=2, outline="#0000ff", fill="")
def inc_ratio(self):
self.tgt_ratio = self.tgt_ratio + 0.5
self.tgt_ratio = min([12.0, self.tgt_ratio])
self.lblstr.set("%d%%" % int(self.tgt_ratio * 100))
self.scale_canvas()
def dec_ratio(self):
self.tgt_ratio = self.tgt_ratio - 0.5
self.tgt_ratio = max([0.5, self.tgt_ratio])
self.lblstr.set("%d%%" % int(self.tgt_ratio * 100))
self.scale_canvas()
def scale_canvas(self):
v = self.tgt_ratio / self.now_ratio
cw = self.canvas.winfo_width()
ch = self.canvas.winfo_height()
self.canvas.scale(tk.ALL, cw / 2, ch / 2, v, v)
self.now_ratio = self.now_ratio * v
def main():
root = tk.Tk()
app = App(master=root)
app.mainloop()
if __name__ == '__main__':
main()
使用画像は以下。
_lena_std.png
py 05_canvas_scale.py で実行。
うすうす予想はしていたけれど、画像は拡大縮小しないやん…。図形だけやん…。まあ、.scale() が画像も拡大縮小してくれるメソッドなら、皆 Pillow を使わずにコレで処理しているはずだけど、しかしそうではないわけで…。巷の解説ページは、自分でスクリプトを書いて動作確認をせずに、画像も変化するものと思い込んで紹介しているのだろうな…。
さておき。キャンバスに対して描画された、矩形、ポリゴン、楕円等は、たしかに拡大縮小しているように見える。線の太さは変わってないけれど、そこは変化しないほうが都合がいいのだろう…。あくまで、各図形の座標情報だけが拡大縮小される、と捉えればいいのだろうか。
[ ツッコむ ]
以上、1 日分です。