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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

ウィンドウ

コンピューター用語において、ウィンドウとはユーザとプログラムのやり取りを可能にするGUIの枠組みのことをいいます。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

3489閲覧

tkinterでウィンドウに自作関数を用いて新たなフレームを貼りつける方法が知りたいです

hinata1211

総合スコア5

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

ウィンドウ

コンピューター用語において、ウィンドウとはユーザとプログラムのやり取りを可能にするGUIの枠組みのことをいいます。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/04/10 14:58

前提・実現したいこと

Pythonでtkinterを使用していたところ、ウィンドウ上のフレームを削除して新たなフレームを貼ろうとしたところ、以下のようなエラーメッセージが表示されました。

発生している問題・エラーメッセージ

Traceback (most recent call last): File "C:\Users\hinat\Desktop\zikken\zikken.py", line 127, in <module> select_project() File "C:\Users\hinat\Desktop\zikken\zikken.py", line 49, in select_project self.frame_app = ttk.Frame(win) File "C:\Users\hinat\AppData\Local\Programs\Python\Python39\lib\tkinter\ttk.py", line 735, in __init__ Widget.__init__(self, master, "ttk::frame", kw) File "C:\Users\hinat\AppData\Local\Programs\Python\Python39\lib\tkinter\ttk.py", line 552, in __init__ tkinter.Widget.__init__(self, master, widgetname, kw=kw) File "C:\Users\hinat\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 2572, in __init__ self.tk.call( _tkinter.TclError: NULL main window

該当のソースコード

Python

1import tkinter as tk 2import tkinter.ttk as ttk 3 4def startup(): 5 st = tk.Tk() 6 st.title('startup') 7 st.geometry('300x100+400+250') 8 9 label_1 = tk.Label(st, text = 'システム名orロゴ') 10 label_1.grid(column=0, row=0, sticky=tk.W) 11 12 launch(st) 13 st.mainloop() 14 15def launch(st): 16 17 st.after(1000, lambda: st.destroy()) 18 19def open_or_new(): 20 global frame 21 frame = ttk.Frame(win) 22 frame.pack(fill=tk.BOTH, pady=20) 23 24 25 btn_open = ttk.Button(frame, text='開く', command=lambda:selected_open(frame, win)) 26 btn_open.place(x=400, y=7) 27 btn_open.pack() 28 29 btn_new = ttk.Button(frame, text='新規', command=lambda:selected_new(frame, win)) 30 btn_new.place(x=400, y=7) 31 btn_new.pack() 32 33 frame.pack(fill=tk.BOTH, pady=20) 34 win.mainloop() 35 36def selected_open(frame, win): 37 global open_new 38 open_new = 'open' 39 frame.destroy() 40 41def selected_new(frame, win): 42 global open_new 43 open_new = 'new' 44 45def select_project(): 46 global frame_app 47 48 self.frame_app = ttk.Frame(win) 49 frame_app.pack(fill=tk.BOTH, pady=20) 50 51 label = ttk.Label(frame,text = "filename:") 52 label.grid(column=0, row=0, sticky=tk.W) 53 label.place(x=10, y=7) 54 55 landString = tk.StringVar() 56 entry = ttk.Entry(frame, width=50, textvariable=landString) 57 entry.grid(column=1, row=0, padx=10) 58 entry.place(x=70, y=10) 59 60 btn_c = ttk.Button(frame, text='選択', command = lambda:openfile(entry)) 61 btn_c.place(x=400, y=7) 62 63 btn_o = ttk.Button(frame, text=' 開く ', command = lambda: open_and_close(win, frame, entry)) 64 btn_o.place(x=400, y=100) 65 66 label.pack() 67 entry.pack() 68 btn_o.pack() 69 btn_c.pack() 70 71 win.mainloop() 72 73def openfile(entry): 74 typ = [('音楽ファイル','*.mp3')] 75 dir = 'C:\User' 76 filename = filedialog.askopenfilename(filetypes = typ, initialdir = dir) 77 entry.insert(tk.END, filename) 78 79def open_and_close(win, frame, entry): 80 global filename 81 filename = entry.get() 82 frame.destroy() 83 win.destroy() 84 85def open_project(project): 86 print('open_project') 87 return 0 88 89def open_new_file(): 90 frame = ttk.Frame(win) 91 frame.pack(fill=tk.BOTH, pady=20) 92 93 label = ttk.Label(frame,text = "filename:") 94 label.grid(column=0, row=0, sticky=tk.W) 95 label.place(x=10, y=7) 96 97 landString = tk.StringVar() 98 entry = ttk.Entry(frame, width=50, textvariable=landString) 99 entry.grid(column=1, row=0, padx=10) 100 entry.place(x=70, y=10) 101 102 btn_c = ttk.Button(frame, text='選択', command = lambda:openfile(entry)) 103 btn_c.place(x=400, y=7) 104 105 btn_o = ttk.Button(frame, text=' 開く ', command = lambda: open_and_close(win, frame, entry)) 106 btn_o.place(x=400, y=100) 107 108 label.pack() 109 entry.pack() 110 btn_o.pack() 111 btn_c.pack() 112 113 win.mainloop() 114 115def calculation(filename): 116 frame = ttk.Frame(win) 117 frame.pack(fill=tk.BOTH, pady=20) 118 119 label = ttk.Label(frame,text = "計算中...") 120 label.grid(column=0, row=0, sticky=tk.W) 121 label.place(x=10, y=7) 122 123 label.pack() 124 125 win.after(1000, lambda: win.destroy()) 126 127 win.mainloop() 128 129def output(filename): 130 frame = ttk.Frame(win) 131 frame.pack(fill=tk.BOTH, pady=20) 132 133 label = ttk.Label(frame,text = "出力画面:"+filename) 134 label.grid(column=0, row=0, sticky=tk.W) 135 label.place(x=10, y=7) 136 137 label.pack() 138 139 win.mainloop() 140 141if __name__ == "__main__": 142 143 startup() 144 145 # rootメインウィンドウの設定 146 global win 147 win = tk.Tk() 148 win.title("title") 149 win.geometry("750x500+400+250") 150 151 open_or_new() 152 153 if open_new == 'open': 154 filename = '' 155 select_project() 156 print(filename) 157 results = open_project(filename) 158 159 else: 160 filename = '' 161 open_new_file() 162 calculation(filename) 163 164 output(filename) 165

試したこと

エラーが発生している関数に引数をつけてみたり、グローバル変数を使用して試行錯誤してみたのですが、どうしてもエラーが出てしまいました。改善方法などがあれば是非教えていただきたいです。
注)作成中のコードな為、エラーが発生している以降の関数は未完成のものです。

補足情報(FW/ツールのバージョンなど)

Pythonのバージョンは3.9.2です。

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

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

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

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

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

guest

回答2

0

ベストアンサー

問題点: 破棄済のウィンドウに対する操作

問題を再現する最小限のコード

python

1import tkinter as tk 2from tkinter import ttk 3 4win = tk.Tk() 5win.destroy() # ルートオブジェクトを破棄すると 6 7# 新しく初期化からし直す必要がある 8# win = tk.Tk() 9frame = ttk.Frame(win) 10frame.pack() 11 12win.mainloop()

解決策:

複数のウィンドウが必要な場合は、tkinter.Toplevel を使います。

プログラム中で tkinter.Tk() と mainloop() 呼び出しは、一度のみにする方法をお勧めします。

python

1 2import tkinter as tk 3from tkinter import ttk 4 5root = tk.Tk() 6root.withdraw() # メインウィンドウを非表示 7 8def launch(win): 9 win.destroy() 10 root.deiconify() # メインウィンドウを表示 11 12def startup(): 13 win = tk.Toplevel() 14 win.after(1000, launch, win) 15 16root.after_idle(startup) 17root.mainloop() 18 19

問題点2: 画面遷移の方法

  • A: ウィジェットを生成・破棄(destroy) する
  • B: ウィジェットをレイアの様に重ね合わせて配置し、レイア操作により画面切り替えを行う(tkraise)
  • C: ttk.Notebook をタブを非表示にして使う。(実装内部ではBと同じ)

そもそもの問題が、Tk() オブジェクトに対する destroy() が問題なので、
画面遷移であれば、他の実装方法でも問題を回避できます。詳しくは tkraise について調べて下さい。
FredericChang さんの回答のコードが B の方法に該当します。

投稿2021/04/12 01:33

teamikl

総合スコア8760

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

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

0

あなたのコードを見て複数のwin.mainloop()とst.mainloop()を見ました。 ご理由は何ですか。

下のコードがMultiPageの機能を実現します。ご参考ください。

python

1 2try: # python 3 3 from tkinter import font as tkfont # python 3 4 import tkinter as tk 5 from tkinter import ttk 6 from tkinter import messagebox 7 from tkinter import LabelFrame 8 from functools import partial 9 import json 10 import DNDTemplate 11except ImportError: 12 import Tkinter as tk # python 2 13 import tkFont as tkfont # python 2 14 15from tkcalendar import Calendar, DateEntry 16 17 18COLOR1 = "Blue" 19COLOR2 = "Gold" 20COLOR3 = "Red" 21jsondata = {} 22agent={} 23content={} 24type={} 25 26class SampleApp(tk.Tk): 27 28 def __init__(self, *args, **kwargs): 29 tk.Tk.__init__(self, *args, **kwargs) 30 31 self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic") 32 self.title('configurator') 33 self.grid_rowconfigure(0, weight=1) 34 self.grid_columnconfigure(0, weight=1) 35 screen_w = self.winfo_screenwidth() 36 screen_h = self.winfo_screenheight() 37 self.maxsize(width=screen_w, height=screen_h) 38 rw = int(screen_w / 2) 39 rh = int(screen_h / 2) 40 self.geometry('{}x{}+{:g}+{:g}'.format(rw, rh, rw / 2, rh / 2)) 41 # root.geometry("1000x1000") 42 # root.maxsize(1200, 1200) 43 self.configure(bg="lightgrey") 44 45 def on_closing(): 46 if messagebox.askokcancel("Quit", "Do you want to quit?"): 47 self.destroy() 48 49 self.protocol("WM_DELETE_WINDOW", on_closing) 50 # the container is where we'll stack a bunch of frames 51 # on top of each other, then the one we want visible 52 # will be raised above the others 53 container = tk.Frame(self) 54 container.pack(side="bottom", fill="both", expand=True) 55 container.grid_rowconfigure(0, weight=1) 56 container.grid_columnconfigure(0, weight=1) 57 58 self.menu = tk.Menu(self) 59 self.config(menu=self.menu) 60 self.subMenu = tk.Menu(self.menu) 61 self.menu.add_cascade(label="File", menu=self.subMenu) 62 self.tabControl = ttk.Notebook(self) 63 64 self.tab1 = ttk.Frame(self.tabControl) 65 self.tab2 = ttk.Frame(self.tabControl) 66 self.tab3 = ttk.Frame(self.tabControl) 67 68 69 self.tabControl.add(self.tab1, text='Tab 1') 70 self.tabControl.add(self.tab2, text='Tab 2') 71 self.tabControl.add(self.tab3, text='Tab 3') 72 73 74 self.tabControl.pack(expand=0, fill="both") 75 self.tabControl.bind('<Button-1>', self.on_click) 76 # tabControl.tab(0, state="normal") 77 # tabControl.tab(1, state="disabled") 78 79 self.frames = {} 80 # for F in (StartPage, PageOne, PageTwo): 81 for F in (FirstPage, SecondPage, ThirdPage): 82 page_name = F.__name__ 83 frame = F(parent=container, controller=self) 84 self.frames[page_name] = frame 85 86 # put all of the pages in the same location; 87 # the one on the top of the stacking order 88 # will be the one that is visible. 89 frame.grid(row=0, column=0, sticky="nsew") 90 91 self.show_frame("FirstPage") 92 93 def on_click(self,event): 94 print('widget:', event.widget) 95 print('x:', event.x) 96 print('y:', event.y) 97 98 # selected = nb.identify(event.x, event.y) 99 # print('selected:', selected) # it's not usefull 100 clicked_tab = self.tabControl.tk.call(self.tabControl._w, "identify", "tab", event.x, event.y) 101 print('clicked tab:', clicked_tab) 102 103 active_tab = self.tabControl.index(self.tabControl.select()) 104 print(' active tab:', active_tab) 105 page_name = "" 106 # if clicked_tab == active_tab: 107 # self.tabControl.forget(clicked_tab) 108 if clicked_tab == 0: 109 page_name = "FirstPage" 110 elif clicked_tab == 1: 111 page_name = "SecondPage" 112 elif clicked_tab == 2: 113 page_name = "ThirdPage" 114 else: 115 page_name = "DragAndDrop" 116 117 frame = self.frames[page_name] 118 frame.tkraise() 119 120 def show_frame(self, page_name): 121 '''Show a frame for the given page name''' 122 # if page_name == 'SecondPage': 123 # self.tabControl.select(tab_id=1) 124 frame = self.frames[page_name] 125 frame.tkraise() 126 127class FirstPage(tk.Frame): 128 #User Information Page 129 def __init__(self, parent, controller): 130 tk.Frame.__init__(self, parent) 131 self.controller = controller 132 title = tk.Label(self, text="Type of test") 133 title.grid(row=0, column=0, rowspan =1, columnspan=1) 134 # separator = ttk.Separator(self, orient='horizontal') 135 # separator.grid(row=1, column=0, rowspan =10, columnspan=5) 136 137 self.vars = tk.StringVar() 138 self.vars1 = tk.StringVar() 139 self.vars2 = tk.StringVar() 140 141 142 143 EntryForCustomerName = tk.Label(self, text="Customer Name:") 144 EntryForCustomerName.grid(row=1, column=0, rowspan =1, columnspan=1) 145 self.Btn_CustomerName = tk.Entry(self, width=30, textvariable=self.vars) 146 self.Btn_CustomerName.grid(row=1, column=1, rowspan =1, columnspan=1) 147 148 EntryForProjectName = tk.Label(self, text="Project Name:") 149 EntryForProjectName.grid(row=2, column=0, rowspan=1, columnspan=1) 150 151 self.Btn_ProjectName = tk.Entry(self, width=30, textvariable=self.vars1) 152 self.Btn_ProjectName.grid(row=2, column=1, rowspan=1, columnspan=1) 153 154 EntryForDate = tk.Label(self, text="Date:") 155 EntryForDate.grid(row=3, column=0, rowspan=1, columnspan=1) 156 self.cal = DateEntry(self, width=12, background='darkblue', 157 foreground='white', borderwidth=2) 158 159 self.cal.grid(row=3, column=1, rowspan =1, columnspan=1) 160 Btn_NextPage = tk.Button(self, text='xx', command=lambda: controller.show_frame("SecondPage")) 161 Btn_NextPage.grid(row=4, column=1, rowspan =5, columnspan=1) 162 163 164class SecondPage(tk.Frame): 165 #User Information Page 166 def __init__(self, parent, controller): 167 tk.Frame.__init__(self, parent) 168 self.controller = controller 169 self.radVar = tk.IntVar() 170 171 self.radioGroup = tk.LabelFrame(self, text="Choose") 172 self.radioGroup.grid(row=0, column=0, rowspan=5, columnspan=5,padx= 5, pady= 5) 173 174 # self.ChooseName = tk.Label(self, text="Choose:") 175 # self.ChooseName.grid(row=0, column=0, rowspan =1, columnspan=1) 176 177 self.rad1 = tk.Radiobutton(self.radioGroup, text="Temperatur Tests", variable=self.radVar, value=1, command=self.radCall) 178 self.rad1.grid(column=1, row=0, sticky=tk.W, columnspan=3) 179 180 self.rad2 = tk.Radiobutton(self.radioGroup, text="Climate Tests", variable=self.radVar, value=2, command=self.radCall) 181 self.rad2.grid(column=5, row=0, sticky=tk.W, columnspan=3) 182 self.rad1.deselect() 183 self.rad2.deselect() 184 self.Btn_NextPage = tk.Button(self, text='Continue', command=lambda: controller.show_frame("ThirdPage")) 185 self.Btn_NextPage.grid(row=6, column=1, rowspan=1, columnspan=2) 186 187 def radCall(self): 188 radSel = self.radVar.get() 189 if radSel == 1: 190 self.rad2.deselect() 191 else: 192 self.rad1.deselect() 193 194 195class ThirdPage(tk.Frame): 196 # User Information Page 197 def __init__(self, parent, controller): 198 tk.Frame.__init__(self, parent) 199 self.controller = controller 200 self.radVar = tk.IntVar() 201 title = tk.Label(self, text="TempEvent") 202 title.grid(row=0, column=0, rowspan=1, columnspan=1) 203 Volume = tk.Label(self, text="Volume:") 204 Volume.grid(row=1, column=0, rowspan=1, columnspan=1) 205 self.radioGroup1 = tk.LabelFrame(self, text="Volume") 206 self.radioGroup1.grid(row=1, column=1, rowspan=1, columnspan=8,padx= 5, pady= 5) 207 self.arrr_Volume = [] 208 arr_Volume = ["180L", "340L", "600L", "1000L", "1500L", "2000L"] 209 x = 0 210 for i in arr_Volume: 211 x = x + 1 212 self.r = tk.Radiobutton(self.radioGroup1, text=i, value=x, indicatoron=0, width=15) 213 self.r.grid(column=x, row=1, sticky=tk.W, columnspan=1) 214 self.arrr_Volume.append(self.r) 215 for x in self.arrr_Volume: 216 x.deselect() 217 218def main(): 219 app = SampleApp() 220 app.mainloop() 221 222if __name__ == "__main__": 223 main()

投稿2021/04/10 16:57

FredericChang

総合スコア54

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問