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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

7272閲覧

Pythonでダイアログを表示してユーザーが閉じるまで待つには

y20190719

総合スコア12

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2019/07/19 06:29

編集2019/07/22 06:36

ここでは初めての質問です。
Pythonもまだ習い始めたばかりです。(VBAやC#の経験はあります)

ダイアログベースのプログラム
(最初から最後までダイアログが表示されているようなプログラム)
の記述例はネット上にありましたので分かりましたが、
メインのプログラムから一時的にダイアログを表示して、
ダイアログが閉じられたら再びメインのプログラムに戻って、
処理を進めていくようなプログラムの基本的な書き方がよく分かりません。

具体的には、

Pythonのプログラムを実行すると、

  1. 実行条件を設定する設定ダイアログを表示して
    ユーザーが実行条件の設定を完了したら開始ボタンで
    この設定ダイアログを閉じる。
  2. 設定された実行条件に基づいてデータ処理を行い、

  実行結果をファイルに出力する。
3) 処理が終了したことを示す終了ダイアログを表示して
ユーザーからの完了ボタンで
このダイアログを閉じてプログラムを終了する。

という処理を行いたいのですが、

以下のコードでは、
1)のユーザーの設定が終わる前に、
2)3)の処理が実行されてしまいます。

Python

1import tkinter 2import win32api 3 4#flg=0 5 6# 1) 開始処理 7root1=tkinter.Tk() 8root1.title('開始') 9root1.geometry('300x200') 10label1=tkinter.Label(root1,text='実行を開始します') 11label1.grid() 12button1=tkinter.Button(root1,text='開始',command=lambda : pushed1()) 13button1.grid() 14 15#while flg!=1: 16# print(flg) 17 18# 2) 本処理 19win32api.Sleep(10000) 20 21# 3) 終了処理 22root2=tkinter.Tk() 23root2.title('終了') 24root2.geometry('300x200') 25label2=tkinter.Label(root2,text='終了しました') 26label2.grid() 27button2=tkinter.Button(root2,text='完了',command=lambda : pushed2()) 28button2.grid() 29 30#while flg!=2: 31# print(flg) 32 33print('END') 34 35def pushed1(): 36# global flg 37# flg=1 38 root1.destroy() 39 40def pushed2(): 41# global flg 42# flg=2 43 root2.destroy()

1)で開始ボタンが押されるまで、2)以降の処理を実行しないようにするには、
どのように記述すればよいのでしょうか。できましたら、
グローバル変数を使用しない方法でお願いします。
(Windows10,Python 3.7.3)

【追記】

●list1

Python

1import tkinter 2import win32api 3 4def pushed1(): 5 root1.destroy() 6 7def pushed2(): 8 root2.destroy() 9 10#メイン処理 11 12# 1) 開始処理 13root1=tkinter.Tk() 14root1.title('開始') 15root1.geometry('300x200') 16label1=tkinter.Label(root1,text='実行を開始します') 17label1.grid() 18button1=tkinter.Button(root1,text='開始',command=lambda : pushed1()) 19button1.grid() 20 21root1.mainloop() 22 23# 2) 本処理 24win32api.Sleep(10000) 25 26# 3) 終了処理 27root2=tkinter.Tk() 28root2.title('終了') 29root2.geometry('300x200') 30label2=tkinter.Label(root2,text='終了しました') 31label2.grid() 32button2=tkinter.Button(root2,text='完了',command=lambda : pushed2()) 33button2.grid() 34 35root2.mainloop() 36 37print('END')

●list2

Python

1import tkinter 2import win32api 3 4def pushed1(): 5 root1.destroy() 6 7def pushed2(): 8 root2.destroy() 9 10#メイン処理 11 12# 1) 開始処理 13root1=tkinter.Tk() 14root1.title('開始') 15root1.geometry('300x200') 16label1=tkinter.Label(root1,text='実行を開始します') 17label1.grid() 18button1=tkinter.Button(root1,text='開始',command=lambda : pushed1()) 19button1.grid() 20root1.grab_set() 21root1.wait_window(root1) 22 23# 2) 本処理 24win32api.Sleep(10000) 25 26# 3) 終了処理 27root2=tkinter.Tk() 28root2.title('終了') 29root2.geometry('300x200') 30label2=tkinter.Label(root2,text='終了しました') 31label2.grid() 32button2=tkinter.Button(root2,text='完了',command=lambda : pushed2()) 33button2.grid() 34root2.grab_set() 35root2.wait_window(root2) 36 37print('END')

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

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

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

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

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

guest

回答1

0

ベストアンサー

このような他のウィンドウに制御を移さないダイアログを、モーダルダイアログとかモーダルウィンドウとかいいます。
ということで、「tkinter モーダルダイアログ」でぐぐってみればどうでしょう

投稿2019/07/19 07:34

y_waiwai

総合スコア87719

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

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

y20190719

2019/07/22 02:09 編集

回答ありがとうございます。 tkinter モーダルダイアログを使えばよいということですが、 モーダルダイアログでもうまくいかないので、 最初はモーダルのサンプルのコードでの質問をしようとしましたが、 通常のダイアログにget_focusを追加すればモーダルになるのか、 モーダルとモーダルでない場合の違いなど、 基本的なことがまだよく理解できていません。 また、原因が、モーダル固有の問題なのか、 モーダルでない通常のダイアログでも起きる問題なのか、 どちらの問題なのかもよく分からないため、 今回のようなご質問をしました。 このため、 モーダルでないダイアログの挙動の不明点を理解した後に、 モーダルのダイアログで確認してみて、それでも分からなければ、 モーダルのダイアログでの質問を別途新規にしたいと思います。 という事情により、ここでは、tkinterの モーダルでないダイアログの挙動の不明点とその対処方法について、 以下のことを教えて頂けないでしょうか。 問1 サンプルのコードでは、   私の理解では、   このコードを実行すると、まず、   1)の開始のダイアログが表示されて、その10秒後に、   3)の終了のダイアログが表示されるように思えるのですが、   実際には、   このコードを実行すると、何も表示されず、その10秒後に、   1)のダイアログと3)のダイアログがほぼ同時に表示されます。   これはなぜでしょうか。 問2 サンプルのコードの中の   コードの頭の#を消してコメントを外したコードでは、   私の理解では、   このコードを実行すると、   1)のダイアログが表示された後、   OKボタンをクリックするまでは(flgが1になるまでは)   2)の処理は行われず、   OKボタンをクリックすると(flgが1になると)   2)の処理に進むように思えるのですが、   実際には、   このコードを実行すると、   2)の直前のprint(flg)が実行されていますが、   1)のダイアログは表示されません。   これはなぜでしょうか。 問3 サンプルのコードを実行すると、   1)のダイアログが表示されて、   1)のダイアログの開始ボタンがクリックされると、   1)のダイアログが閉じて、2)の処理に進み、   2)の処理が終わると3)のダイアログが表示されて、   3)のダイアログの完了ボタンがクリックされると、   3)のダイアログが閉じて終了するようにするには、   サンプルのコードをどのように修正すればよいのでしょうか。 よろしくお願いします。
y_waiwai

2019/07/22 03:31

Windowsのウィンドウ描画動作について簡単に解説しますと、 Windowsメッセージというもので描画動作も含め、あらゆるイベントやマウス動作などの処理を進めていきます > 1)の開始のダイアログが表示されて というのは、この時点ではダイアログを表示させるメッセージを発行しています。このあと、そのメッセージをWindowsのAPIが処理してダイアログが描画されます win32api.Sleep(10000) というのは問答無用に10秒待つという動作なために、メッセージ動作やその他の動作も中断させてしまいます 問2も同様に、OKボタンクリックするまでの間にメッセージ処理をするコードが書かれてないため、ウィンドウ描画が止まったままになってます
y20190719

2019/07/22 06:38

>OKボタンクリックするまでの間にメッセージ処理をするコードが書かれてないため (最初の質問の最後に追記しました)list1のようにしましたら、 期待通りの動作をするようになりました。 ありがとうございました。 ところで、list1はモーダルではないダイアログと思われますが、 モーダルではないダイアログ側の処理の中にgrab_set()を記述すれば、 モーダルダイアログになるのでしょうか。 例えば、list2のダイアログはモーダルダイアログになるのでしょうか。 よろしくお願いします。
y_waiwai

2019/07/22 07:02

Windowsネイティブ(?)のアプリでいうところのモーダルウィンドウと同一、という訳にはいかないと思いますが、ぐぐるとそれで実施している例が多いようですね 実際の動作で確認して問題がないならいいんではないでしょうか
y20190719

2019/07/22 07:15

ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問