mieki256's diary



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

#1 [python] tkinterのScrollbarについて勉強

Python + tkinter で、以下のようなことをしたい。
動作確認環境は以下。
以下のページを参考にして実験してみた。

_Tkinterの使い方: スクロールバー(Scrollbar)の使い方 | だえうホームページ
_python - Tkinter button expand using grid - Stack Overflow
_python tkinter キャンバスのスクロールバーについて

たぶん、できた、ような気がする。こんな感じになった。

_02_scrollbar_canvas.py
try:
    # Python 2.7
    import Tkinter as tk
    # import ttk
except Exception:
    # Python 3.x
    import tkinter as tk
    # from tkinter import ttk

from PIL import Image
from PIL import ImageTk

imgfile = "tex_1024.png"

app = tk.Tk()

frame = tk.Frame(app, bg="green")
frame.pack(expand=1, fill=tk.BOTH)

frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)

# create Canvas
canvas = tk.Canvas(frame, bg="#888888")
canvas.grid(row=0, column=0, sticky=tk.N + tk.S + tk.W + tk.E)

# create Scrollbar
xbar = tk.Scrollbar(frame, orient=tk.HORIZONTAL, command=canvas.xview)
ybar = tk.Scrollbar(frame, orient=tk.VERTICAL, command=canvas.yview)
xbar.grid(row=1, column=0, sticky=tk.W + tk.E)
ybar.grid(row=0, column=1, sticky=tk.N + tk.S)
canvas.config(xscrollcommand=xbar.set)
canvas.config(yscrollcommand=ybar.set)

# load png image, set to canvas
im = Image.open(imgfile)
photo_image = ImageTk.PhotoImage(im)
canvas.create_image(16, 16, anchor=tk.NW, image=photo_image)

# set scroll region
iw = photo_image.width()
ih = photo_image.height()
region = (0, 0, iw + 32, ih + 32)
canvas.config(scrollregion=region)

# set drag scroll
canvas.bind("<ButtonPress-1>", lambda e: canvas.scan_mark(e.x, e.y))
canvas.bind("<B1-Motion>", lambda e: canvas.scan_dragto(e.x, e.y, gain=1))

app.mainloop()

動作に必要なpng画像は以下。

_tex_1024.png

py 02_scrollbar_canvas.py と打って実行。こうなった。



スクロールバーを動かすとキャンバス内の画像の表示位置も変わっているし、ウインドウサイズを変更するとキャンバスのサイズも追従して変化している。更に、キャンバス内をマウスの左ボタンでドラッグしてスクロールができるようにもなった。これで目的は果たせそう。

少し解説。 :

ウインドウサイズを変更した際に、.grid() でレイアウトしたウィジェットのサイズを追従させて変化させるには、weight= を使う。

frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)

上記の指定の場合、.grid() で配置した (0,0) のウィジェットのサイズが、親に追従するようになる。

ちなみに、.pack() でレイアウトしたウィジェットのサイズを親に追従させたい場合は、expand=1, fill=tk.BOTH を指定することになる。

frame.pack(expand=1, fill=tk.BOTH)

マウスボタン押しのドラッグでキャンバス内をPANさせたい場合は、以下のような記述でいいらしい。

canvas.bind("<ButtonPress-1>", lambda e: canvas.scan_mark(e.x, e.y))
canvas.bind("<B1-Motion>", lambda e: canvas.scan_dragto(e.x, e.y, gain=1))


余談。tkinter のキャンバスに画像を表示したい場合、Pillow (PIL) を使って画像を読み込んで、ImageTk.PhotoImage() で tkinter が利用できる状態に変換するのがヨサゲ。と言うのも、Python 2.7.18 32bit + tkinter (Tkinter) の機能で png画像を読み込もうとしたらエラーになってしまったので…。Pillow を経由すれば、どんな画像フォーマットも読み込んで表示できるようになるはず。
im = Image.open(imgfile)
photo_image = ImageTk.PhotoImage(im)
canvas.create_image(16, 16, anchor=tk.NW, image=photo_image)

以上、1 日分です。

過去ログ表示

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