質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

3回答

2076閲覧

tkinter でウィンドウを一個ずつ生成するのに sleep を使うと全部止まる

CleanDiesel

総合スコア15

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

0クリップ

投稿2020/04/03 16:33

Tkinter でウィンドウを一定時間ごとに生成していくというプログラムですが、なぜかボタンを押して一秒ごとにウィンドウが生成されるのではなく、10秒後に一気に10個ウィンドウが出てきます。

python

1 2from tkinter import * 3import time 4 5def generate_mother(): 6 for i in range(10): 7 generate() 8 time.sleep(1) 9 10def generate(): 11 root2 = Toplevel() 12 13root = Tk() 14button = Button(root, text = "foo", command = generate_mother) 15button.pack() 16 17root.mainloop()

###環境
python3.6.9
tkinter8.6

masteroferror👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

asyncioを使った非同期版も紹介。(取りあえず動く程度のサンプルです)

非同期処理が不要な場合は冗長になるので、お勧めの解決策というわけでは有りません。念の為。

python

1# このコードの目的: コールバックを使ったループではなくfor文で書く。 2# (for文のコードの可読性を残す) 3 4import asyncio 5import tkinter as tk 6 7# 新規ウィンドウを num 枚開く 8async def generate_mother(num): 9 for i in range(num): 10 await asyncio.sleep(1) 11 root2 = tk.Toplevel() 12 13 14# 定期的に tk へ処理を戻す 15async def tk_mainloop(root, interval=0.2): 16 try: 17 while True: 18 root.update() 19 await asyncio.sleep(interval) 20 except tk.TclError: # XXX エラー処理手抜き 21 pass 22 23 24def main(): 25 from asyncio import ensure_future, get_event_loop 26 27 ## GUI生成 28 root = tk.Tk() 29 button = tk.Button(root, text="OK") 30 button.pack() 31 32 ## 非同期関連の処理 33 34 # ボタンクリック時のイベント (非同期版) 35 button["command"] = lambda: ensure_future(generate_mother(10)) 36 37 # root.mainloop の代理 (非同期版) 38 mainloop = ensure_future(tk_mainloop(root)) 39 40 ## mainloop の完了時に run_forever() 内のループを抜ける 41 mainloop.add_done_callback(lambda future: loop.stop()) 42 43 ## ループ実行 44 loop = get_event_loop() 45 try: 46 # asyncio にとっての メインループ に相当。 47 # rootウィンドウが閉じる迄ここで止まる。 48 loop.run_forever() 49 except KeyboardInterrupt: 50 pass 51 finally: 52 loop.stop() 53 54 55if __name__ == "__main__": 56 main()

投稿2020/04/03 23:36

teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Pythonの関数が呼ばれる時は、一時的に処理がPython側に移っている為、
GUIを動かす為には、イベントの処理が終わった後、
tk に描画処理を戻す必要があります。

def generate(num): #Toplevelはアプリケーション内のウィンドウ time.sleep(num) root2 = Toplevel() root.update() # <- これでウィンドウは開きますが・・・次にsleepに来るとtkはまたフリーズ

tkinter で同様の事をする場合は、after() が使えます。

python

1from tkinter import * 2import time 3 4def generate_mother(): 5 root.after(1000, generate) 6 7def generate(num=10): 8 if num <= 0: 9 return 10 root2 = Toplevel() 11 root.after(1000, lambda: generate(num-1)) 12 13root = Tk() 14button = Button(root, text = "foo", command = generate_mother) 15button.pack() 16 17root.mainloop()

投稿2020/04/03 20:28

編集2020/04/03 20:32
teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

描画の処理はgenerate_motherの処理が完全に終わった時に呼ばれてるっぽいのでthreadingを使って
ほぼ同時にgenerate関数の処理を開始してsleepの値を制御して一定の時間ごとに処理するコードをゴリ押しで作ってみました!

Python

1from tkinter import * 2import time 3import threading 4 5def generate(num): 6 #Toplevelはアプリケーション内のウィンドウ 7 time.sleep(num) 8 root2 = Toplevel() 9 10def callback(event): 11 #target=generateはgenerateという関数を呼び出し 12 #引数iを渡して時間制御 13 for i in range(num): 14 th[i] = threading.Thread(target=generate, args=(i,)) 15 th[i].start() 16 17root = Tk() 18num = 10 19th = [0] * num 20 21print(th) 22 23#buttonをつくる 24button = Button(root) 25button["text"] = "foo" 26#<1>はボタンが押された時に呼び出される 27button.bind("<1>",callback) 28 29button.pack() 30#rootを閉じると子も閉じる 31# 一度作ったら通らない 32 33root.mainloop()

環境

Python 3.8.2

以下実装風景
https://www.youtube.com/watch?v=jkOU6XgwC0M

投稿2020/04/03 19:47

編集2020/04/03 19:49
masteroferror

総合スコア15

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問