python GUI tcl/tk  子ウィンドウ起動  改善版:起動引数

# 実行サンプル
子ウィンドウ起動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423803/6bc2b158-ec33-a9a1-c926-df86e9aa1c94.png)


・ボタン押下で 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

# ソースコード
https://github.com/sakurataiko1/python_sample/tree/main/sample_tcltk/tcl_childWindow_02


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" )
```