実行サンプル
子ウィンドウ起動
・ボタン押下で mode 指定して、子ウィンドウ起動
モード指定により、画面GUIが違うものとして表示される
・ChildWindowが既に存在する場合はメッセージボックスで通知し、新たに開かないようにする
・childWin.py で mode を引数として受け取る
・childWin 起動後、画面が閉じられるまで、次の処理は実行されないようにする
・00_mainWin.py と childWin.py で情報受け渡しする
・ childWin.py func_initを複数用意することで、GUI表示や、渡す引数を自由度高く切り替えできるようにする
例)↓これらを 00_mainWin.py から呼び出す
func_init_01(),
func_init_02(self, 引数リストなど, 引数, 引数)
実行環境
windows10
python3.9.5
pythonモジュール tcl/tk
実行手順
ソースコードを作成する
windowsコマンドプロンプトでプログラム作成したフォルダに移動し、下記実行する
python プログラム名.py
参考 URL
#参考 https://qiita.com/hatorijobs/items/ddd435d749cd97581a6c
ソースコード
00_mainWin.py
#参考 https://qiita.com/hatorijobs/items/ddd435d749cd97581a6c
import tkinter as tk
from tkinter import messagebox
import childWin
class MainWindow(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
#self.master.geometry(str(320) + "x" + str(200) + "+" + str(200) + "+" + str(200))
self.master.geometry("350x400+200+200")
self.master.title("parent window")
self.child_window1 = None # ChildWindowのインスタンスを保持するための変数
self.g_parent_str = ""
self.create_widgets()
def create_widgets(self):
# 部品定義
msg = '子ウィンドウ起動 複数起動なし(既に起動していたら起動しない)\n'
msg += '子ウィンドウが閉じるまでは、親ウィンドウは次の処理に進みません\n子ウィンドウが閉じたらメッセージが表示されます'
self.labelP1 = tk.Label(self, text=msg)
self.buttonP1 = tk.Button(self, text="子ウィンドウ起動 1", command=self.func_on_buttonP1_clicked)
# 部品配置
self.labelP1.pack(side='top', anchor='w', padx=5, pady=5)
self.buttonP1.pack(side='top', anchor='w', padx=5, pady=5)
# 部品定義
self.button2 = tk.Button(self, text="子ウィンドウ起動 2", command=lambda: self.open_child_window1(2))
self.button3 = tk.Button(self, text="子ウィンドウ起動 3", command=lambda: self.open_child_window1(3))
self.button4 = tk.Button(self, text="子ウィンドウ起動 4", command=lambda: self.open_child_window1(4))
self.button5 = tk.Button(self, text="子ウィンドウ起動 5", command=lambda: self.open_child_window1(5))
# 部品配置
self.button2.pack(side='top', anchor='w', padx=5, pady=5)
self.button3.pack(side='top', anchor='w', padx=5, pady=5)
self.button4.pack(side='top', anchor='w', padx=5, pady=5)
self.button5.pack(side='top', anchor='w', padx=5, pady=5)
# 部品定義
self.label1 = tk.Label(self, text='子ウィンドウへの情報送付欄')
self.entry_p1 = tk.Entry(self)
# 部品配置
self.label1.pack(side='top', anchor='w') # 左寄せ: anchor='w'
self.entry_p1.pack(side='top', anchor='w')
#
self.entry_p1.insert(0,"from paretn test01")
# 部品定義
self.label2 = tk.Label(self, text='子ウィンドウから情報受け取り 01')
self.entry_p2 = tk.Entry(self)
# 部品配置
self.label2.pack(side='top', anchor='w')
self.entry_p2.pack(side='top', anchor='w')
# 部品定義
self.label3 = tk.Label(self, text='子ウィンドウから情報受け取り 02')
self.entry_p3 = tk.Entry(self)
# 部品配置
self.label3.pack(side='top', anchor='w')
self.entry_p3.pack(side='top', anchor='w')
def func_on_buttonP1_clicked(self):
self.open_child_window1(1)
def open_child_window1(self, in_mode):
DEBUGstr = "[DEBUG]00_mainWin.py func_on_button1_clicked "
# ChildWindowが既に存在する場合はメッセージボックスで通知し、新たに開かないようにする
if self.child_window1 is not None:
messagebox.showinfo("Info", "Child Window is already open.")
else:
if(in_mode == 1):
print(DEBUGstr, " 01")
mode = '01'
self.child_window1 = childWin.ChildWindow(self.master, self, in_mode)
self.child_window1.func_init_01()
if(in_mode == 2):
self.child_window1 = childWin.ChildWindow(self.master, self, in_mode)
self.child_window1.func_init_01() # 引数:in_mode で子ウィンドウの表示や処理を切り替える
if(in_mode == 3):
self.child_window1 = childWin.ChildWindow(self.master, self, in_mode)
self.child_window1.func_init_01() # 引数 in_mode で子ウィンドウの表示や処理を切り替える
if(in_mode == 4 ):
self.child_window1 = childWin.ChildWindow(self.master, self, in_mode)
list1 = ['4_1_1', '4_1_2']
list2 = ['4_2_1', '4_2_2']
self.child_window1.func_init_04(list1, list2) # 子ウィンドウ側の別関数を呼び出すことで、子ウィンドウの表示や処理を切り替える 渡したい引数を多数渡せる
if(in_mode == 5 ):
list1 = ['5_1_1', '5_1_2']
list2 = ['5_2_1', '5_2_2']
str1 = "test5"
self.child_window1 = childWin.ChildWindow(self.master, self, in_mode)
self.child_window1.func_init_05(list1, list2, str1) # 子ウィンドウ側の別関数を呼び出すことで、子ウィンドウの表示や処理を切り替える 渡したい引数を多数渡せる
msg = "子ウィンドウが閉じられました。親ウィンドウの処理が再開されます"
print(DEBUGstr, msg)
tk.messagebox.showinfo("info", msg)
if __name__ == "__main__":
root = tk.Tk()
app = MainWindow(master=root)
app.pack()
app.mainloop()
childWin.py
#参考 https://qiita.com/hatorijobs/items/ddd435d749cd97581a6c
import tkinter as tk
from tkinter import messagebox
import datetime
class ChildWindow:
def __init__(self, master, parent, mode):
#super().__init__(master)
self.master = master
self.parent = parent
self.mode = mode
self.window = None
self.g_cnt = 0
print("[DEBUG]childWin.py __init__")
def func_init_01(self):
self.create_widgets()
self.window.mainloop()
def func_init_04(self, in_list1, in_list2):
tmpstr = 'モード4で起動しました\n'
tmpstr += ', ' + ' '.join(in_list1)
tmpstr += ', ' + ' '.join(in_list2)
tk.messagebox.showinfo("info", tmpstr)
self.create_widgets()
self.window.mainloop()
def func_init_05(self, in_list1, in_list2, in_str1):
tmpstr = 'モード5で起動しました\n'
tmpstr += ', ' + ' '.join(in_list1)
tmpstr += ', ' + ' '.join(in_list2)
tmpstr += ', ' + ' '.join(in_str1)
tk.messagebox.showinfo("info", tmpstr)
self.create_widgets()
self.window.mainloop()
# -start- org
# def this_window_close(self):
# self.window.withdraw()
# # ↓これをしないと、子ウィンドウを閉じた後に、再度開くことが出来なくなる。
# self.window = None
# return "break"
# -end- org
def this_window_close(self):
self.window.withdraw()
# ↓これをしないと、子ウィンドウを閉じた後に、再度開くことが出来なくなる。
#self.window = None
self.parent.child_window1 = None # 親Windowで持っているChildWindow情報のリセット
self.window.quit() # エラーメッセージが出るがこれを入れないと、親ウィンドウで次の処理がされない self.window.mainloop()の終了
self.window.destroy()
return "break"
def create_widgets(self):
if not self.window:
self.window = tk.Toplevel(self.master)
# ×ボタンの処理をカスタマイズする
self.window.protocol('WM_DELETE_WINDOW', self.this_window_close)
#self.geometry(str(400) + "x" + str(200) + "+" + str(400) + "+" + str(400))
self.window.geometry("350x300+400+400")
self.window.title("child window")
# 部品定義 全体レイアウトのためのフレーム
self.frame1 = tk.Frame(self.window)
self.frame2 = tk.Frame(self.window)
self.frame3 = tk.Frame(self.window)
self.frame4 = tk.Frame(self.window)
self.frame5 = tk.Frame(self.window)
# 部品配置 全体レイアウトのためのフレーム
self.frame1.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
self.frame2.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")
self.frame3.grid(row=2, column=0, padx=10, pady=10, sticky="nsew")
self.frame4.grid(row=3, column=0, padx=10, pady=10, sticky="nsew")
self.frame5.grid(row=4, column=0, padx=10, pady=10, sticky="nsew")
if self.mode == 1:
tk.messagebox.showinfo("info", 'モード1で起動しました')
self.label1 = tk.Label(self.frame1, text="Mode 1: Label 1")
self.label1.pack(side='left')
elif self.mode == 2:
tk.messagebox.showinfo("info", 'モード2で起動しました')
self.label2 = tk.Label(self.frame2, text="Mode 2: Label 2")
self.label2.pack(side='left')
elif self.mode == 3:
tk.messagebox.showinfo("info", 'モード3で起動しました')
self.label_3 = tk.Label(self.frame3, text="Mode 3: Label 3")
self.label_3.pack(side='left')
# 部品定義
self.button_c1= tk.Button(self.frame3, text="親ウィンドウから情報取得", command=self.func_on_button_c1_clicked)
self.entry_c1 = tk.Entry(self.frame3)
# 部品配置
self.button_c1.pack(side='left', padx=5, pady=5)
self.entry_c1.pack(side='left', padx=5, pady=5)
# 部品定義
self.button_c2= tk.Button(self.frame4, text="親ウィンドウへ情報送付", command=self.func_on_button_c2_clicked)
self.entry_c2 = tk.Entry(self.frame4)
# 部品配置
self.button_c2.pack(side='left', padx=5, pady=5)
self.entry_c2.pack(side='left', padx=5, pady=5)
# 部品定義
#self.button_close = tk.Button(self.frame5, text="子ウィンドウを閉じる", command=lambda: self.window.destroy())
self.button_close = tk.Button(self.frame5, text="子ウィンドウを閉じる", command=self.this_window_close)
# 部品配置
self.button_close.pack(side='left', padx=5, pady=5)
# 親に情報送付
self.parent.g_parent_str = "from child:" + datetime.datetime.now().isoformat()
def func_on_button_c1_clicked(self):
msg = self.parent.entry_p1.get()
self.entry_c1.delete(0, tk.END)
self.entry_c1.insert(tk.END, msg)
def func_on_button_c2_clicked(self):
self.g_cnt += 1
self.parent.entry_p2.delete(0, tk.END)
self.parent.entry_p2.insert(0, "from child test1: " + str(self.g_cnt))
self.parent.g_parent_str = "from child test2: " + str(self.g_cnt)
def func_on_buttonC1_clicked(self):
DEBUGstr = "[DEBUG]childWin.py func_on_buttonC1_clicked "
tk.messagebox.showinfo("info", "[DEBUG] child buttonC1 clicked" )