LoginSignup
0
0

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

Last updated at Posted at 2024-05-09

実行サンプル

子ウィンドウ起動

image.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

ソースコード

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0