mieki256's diary



2022/04/08(金) [n年前の日記]

#1 [python] tkinterのCanvas.scaleについて調べてた

Python + tkinter のキャンバス(Canvas)についてググってたら .scale() というメソッドがあると知って、もしやそのメソッドを使えばキャンバスの拡大縮小が簡単にできるのだろうかと気になってきた。巷の解説ページには「図形や画像を拡大縮小できる」と書いてあったりもするようだし…。画像も拡大縮小してくれるならありがたいのだけど、さてはて…。

そんなわけで、試してみた。動作確認環境は以下。
_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 を使わずにコレで処理しているはずだけど、しかしそうではないわけで…。巷の解説ページは、自分でスクリプトを書いて動作確認をせずに、画像も変化するものと思い込んで紹介しているのだろうな…。

さておき。キャンバスに対して描画された、矩形、ポリゴン、楕円等は、たしかに拡大縮小しているように見える。線の太さは変わってないけれど、そこは変化しないほうが都合がいいのだろう…。あくまで、各図形の座標情報だけが拡大縮小される、と捉えればいいのだろうか。

以上です。

過去ログ表示

Prev - 2022/04 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project