TkinterのSpinboxとProgressbarウィジェットの使い方について解説する

スポンサーリンク

Tkinterのこのチュートリアルシリーズでは、TkinterのSpinboxとProgressbarウィジェットについて学びます。

続けて、アプリケーションに追加できるウィジェットをさらに調べていきます。

それでは、例題を使って一つずつ見ていきましょう。


スポンサーリンク

Tkinter Spinbox Widgetを使う

TkinterのSpinboxウィジェットは、固定された値の集合から選択することができるウィジェットです。

TkinterのEntryウィジェットを覚えていますか?エンドユーザが限られた選択肢の中からしか選べないように制限したいとします、ここではあまり役に立ちません!

むしろ、固定された選択肢の中から選びたいはずです。

では、その使い方を見てみましょう。

これは Entry ウィジェットとほぼ同じですが、オプションの引数 values で値のリストを指定します。

これはタプルです。

spin_box = tk.Spinbox(master, values)

値が整数値などの場合は、 from_to という引数を使用して、値の範囲から指定することもできます。

注意: キーワード引数 from_ の末尾にはアンダースコアが付きますが、これは from が Python の予約キーワードであるためです。

spin_box = tk.Spinbox(master, from_, to)

それでは、いくつかの定義済みオプションを持つスピンボックスウィジェットを持つ、シンプルなアプリケーションを作ってみましょう。

ウィジェットを適切な位置に配置するために、グリッドジオメトリマネージャを使用します。

また、各ウィジェットにラベルを付けて、他の人がテキストで識別できるようにします。

import tkinter as tk
 
# Create the master object
master = tk.Tk()
 
# Create a spinbox widget
spinbox_1 = tk.Spinbox(master, values=("Python", "Java", "C++"))
 
# And a label for it
label_1 = tk.Label(master, text="Language")
 
# Create another spinbox widget
spinbox_2 = tk.Spinbox(master, from_=1, to=3)
 
# And a label for it
label_2 = tk.Label(master, text="Value")
 
# Use the grid geometry manager to put the widgets in the respective position
label_1.grid(row=0, column=0)
spinbox_1.grid(row=0, column=1)
 
label_2.grid(row=1, column=0)
spinbox_2.grid(row=1, column=1)
 
# The application mainloop
tk.mainloop()

結果は以下の通りです。

import tkinter as tk
# Necessary for the Progressbar widget
import tkinter.ttk as ttk
progress_bar = ttk.Progressbar(orient, mode, maximum, value)

これを自分で実行すると、スピンボックスウィジェットの両方について、上で提供した特定のリストから値を調整できることがわかります。

このウィジェットの詳細な引数や調整方法については、公式ドキュメントを参照してください。

それでは、ProgressBarウィジェットを見てみましょう。


プログレスバーウィジェットの使い方

Progressbarウィジェットは、長時間実行される操作の状態を表示します。

例えば、何かの処理にどれくらいの時間がかかっているかを視覚化したい場合、Progressbar を使えばそれが可能です!

これは tkinter.ttk モジュールで利用可能なので、別途インポートする必要があります。

progress_bar.start(interval=None)

ここでは、簡単なオプションを使って、その使い方を見ていきます。

全リストはこちらで見ることができます。

progress_bat.step(amount=10)

ここで、orientはプログレスバーの向きを指定します。

これは “horizontal” か “vertical” のどちらかです。


このウィジェットは2つのモードで動作することができます

  • 決定版” -> 作業の総量に対する完了量を表示します。
  • 不確定」-> 作業が進行していることを示すために、単にアニメーションを表示します。

プログレスバーは、バーの現在の 最大値 に達するまで続きます。

プログレスバーの値のインクリメントを開始するには、 progress_bar.start(interval) を使用する必要があります。

これは、 interval ミリ秒ごとに自動的にこれを行います。

ここでは None とし、デフォルト値である 50 ミリ秒に設定します。

import tkinter as tk
import tkinter.ttk as ttk
 
# Create the master object
master = tk.Tk()
 
# Create a progressbar widget
progress_bar = ttk.Progressbar(master, orient="horizontal",
                              mode="determinate", maximum=100, value=0)
 
# And a label for it
label_1 = tk.Label(master, text="Progress Bar")
 
 
# Use the grid manager
label_1.grid(row=0, column=0)
progress_bar.grid(row=0, column=1)
 
# Start auto-incrementing periodically
progress_bar.start()
progress_bar.step(10)
 
# The application mainloop
tk.mainloop()

次に、step() メソッドを使用して、値が amount = 10 ずつ増加することを確認します。

progress_bar['value'] = 0
master.update()

今までのコード一式を載せておきます。

import tkinter as tk
import tkinter.ttk as ttk
import time
 
# Create the master object
master = tk.Tk()
 
# Create a progressbar widget
progress_bar = ttk.Progressbar(master, orient="horizontal",
                              mode="determinate", maximum=100, value=0)
 
# And a label for it
label_1 = tk.Label(master, text="Progress Bar")
 
 
# Use the grid manager
label_1.grid(row=0, column=0)
progress_bar.grid(row=0, column=1)
 
# Necessary, as the master object needs to draw the progressbar widget
# Otherwise, it will not be visible on the screen
master.update()
 
progress_bar['value'] = 0
master.update()
 
while progress_bar['value'] < 100:
    progress_bar['value'] += 10
    # Keep updating the master object to redraw the progress bar
    master.update()
    time.sleep(0.5)
     
# The application mainloop
tk.mainloop()

結果は以下の通りです。

Spinbox Entry 1
Spinbox Entry 1

動くプログレスバーが表示される。

これは value を 0 から 100 まで、50 ミリ秒ごとに 10 単位で増加させる。

しかし、私たちは正しいアプローチをしているのだろうか?

しかし、ここでの問題は、プログレスバーが maximum に達した後、再び 0 にリセットされることです。

これを避けるために、プログレスバーを stop() する必要があります。

しかし、これは思ったより多くの問題を引き起こすことに気づきました。

というのも、その場合、更新中のプログレスバーを得ることができないからです。

最大の問題は、私たちのメインアプリケーションが tk.mainloop() 関数の中で実行されることです。

そのため、リアルタイムで実行するためには、これらすべてを事前に計算する必要があります。

そこで、いくつかググってみたところ、start()stop() を使うのは正しい方法ではないことがわかりました。

なぜなら、プログレスバーがどのように再描画されるかについては何も書かれていないからです。

したがって、(悲しいかな)残された唯一の解決策は、プログレスバーの value を自分自身で手動で更新することです。

StackOverflowに投稿された内容を見ると、他のTkinterプログラマは確かにそのような結論に達しているようです。

ウィジェットの値を自分で修正する

そのために、すべてのTkinterウィジェットは辞書属性を持っており、それを変更することができます! そうです、とても簡単です。

プログレスバーの値を更新するには、次のようにします。

Spinbox Entry 2
Spinbox Entry 2

ただし、masterオブジェクトに、このウィジェットが新しい値で更新されたことを master.update() で通知する必要があります。

では、これらの変更を考慮して、古いコードと間違ったコードを書き直します。

Progress Bar 1
Progress Bar 1

これで、ウィジェットの値を更新するという大変な作業をすべて自分たちで行う一方で、より多くの制御ができるようになりました。

このコードでは、プログレスバーの連続したシーケンスを表示し、valueが100に達したときに停止することができるはずです。

このプログラムが動作することを示す簡単な GIF を以下に示します。

Progress Bar 4
Progress Bar GIF

まとめ

最後に、TkinterのSpinboxとProgressbarウィジェットを使用するためのチュートリアルを終了します。

Tkinterのコンテンツはまだまだ続きますので、お楽しみに。


タイトルとURLをコピーしました