#!python # -*- mode: python; Encoding: utf-8; coding: utf-8 -*- # Last updated: <2025/10/26 15:23:34 +0900> """ ttk.Progressbar sample. indeterminate mode. use queue and threading Windows11 x64 25H2 + Python 3.10.10 64bit """ import tkinter as tk import tkinter.ttk as ttk from tkinter import messagebox import time import queue import threading UPDATE_INTERVAL = 20 after_id = None thread = None que = None abort_fg = False def heavy_job(queue: queue): """ 重い処理 Args: queue (queue): tkinterで処理したい内容を収めるキュー """ for i in range(100): time.sleep(0.03) # 重い処理 # 処理を中断 global abort_fg if abort_fg: return # メインスレッド側で処理したい内容を関数にしておく def func(): pb.step() # プログレスバーの状態を変更 queue.put(func) # キューに関数を収める # 処理終了。終了時の処理を関数にしておく def end_func(): pb.stop() pb.configure(mode="determinate") pbvar.set(0) messagebox.showinfo("Message", "Finish !") # メッセージ表示 btn.configure(state=tk.NORMAL) # ボタンの有効化 queue.put(end_func) # キューに関数を収める def count_up_start(): """ ボタンを押したときの処理 """ btn.configure(state=tk.DISABLED) # ボタンの無効化 pbvar.set(0) # プログレスバーの値を初期化 pb.configure(mode="indeterminate") pb.start(10) # 別スレッドを生成して重い処理を開始 global thread thread = threading.Thread(target=heavy_job, args=(que,)) thread.start() # N msec後にプログレスバーの更新処理を開始 global after_id after_id = root.after(UPDATE_INTERVAL, update_prgressbar) def update_prgressbar(): """ プログレスバーの更新処理 """ global que while not que.empty(): # キューから関数を取り出して実行する func = que.get_nowait() func() # キューが空。次回の更新処理をセット global after_id after_id = root.after(UPDATE_INTERVAL, update_prgressbar) def window_close(): """ ウインドウの閉じるボタンが押された時の処理 """ # 別スレッドに処理の中断を指示 global abort_fg abort_fg = True # 別スレッドの処理が終了するまで待つ global thread if thread is not None: thread.join() thread = None # .after() 使用中なら .after_cancel(ID) で次回の呼び出しをキャンセル global after_id if after_id is not None: root.after_cancel(after_id) after_id = None # アプリを終了。mainloop() から抜ける root.quit() # -------------------- # main root = tk.Tk() root.title("ttk.Progressbar sample 4") # プログレスバーを生成 pbvar = tk.IntVar() pb = ttk.Progressbar(root, length=320, maximum=100, mode="determinate", variable=pbvar) pb.pack(padx=16, pady=8) # ボタンを生成 btn = tk.Button(root, text="Start", command=count_up_start) btn.pack(pady=16) # キューを確保 que = queue.Queue() # ウインドウの閉じるボタンが押された時に呼ばれる関数を指定 root.protocol("WM_DELETE_WINDOW", window_close) root.mainloop()