1.27 複数のメインウィンドウ(mainloop、mainloop(n)、focus_force)
通常、メインウィンドウは 1 つを作成しますが、複数のメインウィンドウを作成することができます。このとき、「mainloop」メソッドはそれぞれのメインウィンドウに対して呼び出しても良いですが、全てのウィンドウが終了したときに終了する場合は一つを実行すれば良いです。最初に呼び出された「mainloop」メソッドが終了するまで、続くコードは実行されません。「mainloop」メソッドの詳細は Misc クラスメソッドを参照して下さい。
複数のメインウィンドウは、それらが全てルートウィンドウとして動作するので、作成するときにシステムに明示的にそのスタック順(表示順)を指定しないと、動作が不定になります。例えば、背面に表示されているウィンドウがアクティブ状態になっていたり、それをマウスクリックしても応答しないという状態が発生します。マウスクリックで手動でウィンドウをアクティブにしてその表示をシステムに指示すると安定します。
アプリケーションでウィンドウのスタック順を指定するには 1.10 項で用いた Misc クラスの「update」メソッドと 1.20 項で用いた Wm クラスの「wm_deiconify」または「deiconify」メソッドを用います。ウィンドウの作成後、「update」でイベント処理の終了を待機した後に「wm_deiconify」または「deiconify」メソッドをウィンドウのスタック順(背面からの表示順)に実行します。
次のプログラムは「root」と「root2」の二つのメインウィンドウを作成して表示しています。「update」メソッドでイベント処理の待機後、「wm_deiconify」メソッドで最初に「root」ウィンドウを、次いで「root2」ウィンドウをスタックしています。「root2」ウィンドウが「root」ウィンドウの前面に表示されます。「mainloop」メソッドを「root」ウィンドウから呼び出しています。それぞれの、ウィンドウはメインウィンドウとして個別に動作します。二つのウィンドウが閉じられると「mainloop」メソッドが終了して、次の「print」コードが実行されます。これは「mainloop」メソッドの引数がデフォルトの「0」に設定されているので、全てのメインウィンドウが無くなったときに終了するためです。
import tkinter as tk | |
root = tk.Tk() | |
root.config(width=300, height=200, bg='blue') | |
root.geometry('+100+100') | |
root2 = tk.Tk() | |
root2.config(width=300, height=200, bg='red') | |
root2.geometry('+140+120') | |
root.update() | |
root.wm_deiconify() | |
root2.wm_deiconify() | |
root.mainloop() | |
print('no Window') |
プログラムを実行すると、ウィンドウが表示されます。二つのウィンドウが閉じられたとき、「mainloop」メソッドの次のコードが実行され下記の文字列が「print」出力されます。
アプリケーションでウィンドウのスタック順を指定する方法としては 、1.25 項で用いた Misc クラスの「lift」または「tkraise」メソッドと Misc クラスの「focus_force」メソッドを用いることができます。
ここで、他のウィンドウの作成を「mainloop」メソッドの実行後にイベント(ボタンなどの操作)で行う場合、ウィンドウのスタックはイベント順に実行されるので「lift」または「tkraise」メソッドは必要ありませんが、フォーカスの設定は「focus_force」メソッドを用いる必要があります。「wm_deiconify」メソッドを用いてもフォーカスは設定されません。
「focus_force」メソッドはウィンドウを含むウィジェットにフォーカスを設定するメソッドで、下記の書式を用います。詳細は Misc クラスメソッドを参照して下さい。
次のプログラムは上と同様に「root」と「root2」の二つのメインウィンドウを作成して表示しています。「focus_force」メソッドで最初に「root」ウィンドウにフォーカスを設定しています。「update」メソッドでイベント処理の待機後、「lift」メソッドで「root2」ウィンドウを前面に表示した後に「focus_force」メソッドで「root2」ウィンドウにフォーカスを設定しています。上のプログラムと同様に「mainloop」メソッドを「root」ウィンドウから呼び出しています。それぞれの、ウィンドウはメインウィンドウとして個別に動作します。二つのウィンドウが閉じられると「mainloop」メソッドが終了して、次の「print」コードが実行されます。これは「mainloop」メソッドの引数がデフォルトの「0」に設定されているので、全てのメインウィンドウが無くなったときに終了します。
import tkinter as tk | |
root = tk.Tk() | |
root.config(width=300, height=200, bg='blue') | |
root.geometry('+100+100') | |
root2 = tk.Tk() | |
root2.config(width=300, height=200, bg='red') | |
root2.geometry('+140+120') | |
root.focus_force() | |
root.update() | |
root2.lift() | |
root2.focus_force() | |
root.mainloop() | |
print('no Window') |
プログラムを実行すると、ウィンドウが表示されます。二つのウィンドウが閉じられたとき、「mainloop」メソッドの次のコードが実行され下記の文字列が「print」出力されます。
「mainloop」メソッドは現在のメインウィンドウの数でそのループを終了することができます。引数にその数を設定します。この設定で、複数のメインウィンドウで「mainloop」メソッドのループを抜ける制御をすることができます。詳細は Misc クラスメソッドを参照して下さい。
次のプログラムは、上と同様に「root」と「root2」の二つのメインウィンドウを作成して表示しています。「mainloop」メソッドの引数を「1」にして「root」ウィンドウから呼び出します。その後、「print」コードで文字列「one Window」を出力して、再度、デフォルトの「mainloop」メソッドを「root」ウィンドウから呼び出しています。この「mainloop」メソッドの終了後に「print」コードで「no Window」を出力しています。ウィンドウの一つを閉じると、最初の「mainloop」メソッドが終了します。これは引数に「1」を設定しているので、ウィンドウが一つ以下になったためです。このループが終了して、次のデフォルト設定の「mainloop」メソッドが実行されます。残りのウィンドウを閉じると、デフォルト設定の「mainloop」メソッドが終了して、次の「print」コードが実行されます。
import tkinter as tk | |
root = tk.Tk() | |
root.config(width=300, height=200, bg='blue') | |
root.geometry('+100+100') | |
root2 = tk.Tk() | |
root2.config(width=300, height=200, bg='red') | |
root2.geometry('+140+120') | |
root.update() | |
root.wm_deiconify() | |
root2.wm_deiconify() | |
root.mainloop(1) | |
print('one Window') | |
root.mainloop() | |
print('no Window') |
プログラムを実行すると、ウィンドウが表示されます。一つのウィンドウが閉じられたとき、最初の「mainloop」メソッドが終了して文字列「one Window」が「print」出力されます。次いで、残りのウィンドウを閉じると文字列「no Window」が「print」出力されます。「print」出力は下記のようになります。
no Window