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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

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

Q&A

2回答

4104閲覧

tkinterで意味不明のNameError

wasuremono_king

総合スコア13

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

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

0グッド

1クリップ

投稿2019/02/28 20:15

プログラミング初心者の自分にわけのわからないエラーが連発しています。

python

1import pygame 2from tkinter import * 3from datetime import datetime 4tk = Tk() 5 6hour = datetime.now().strftime('%H') 7minute = datetime.now().strftime('%M') 8sound = "decision1.mp3" 9 10hour_list = [] 11minute_list = [] 12description_l = [] 13 14def main_window(): 15 tk.title("目覚まし時計") 16 tk.geometry("400x500") 17 18 add = Button(tk,text="add",command=add_window) 19 listbox = Listbox() 20 21 add.grid() 22 listbox.grid() 23def add_window(): 24 adding = Toplevel() 25 adding.title("目覚まし時計") 26 adding.geometry("400x500") 27 28 hour_entry = Entry(adding) 29 minute = Entry(adding) 30 chb = Checkbutton(adding,text="一度のみ") 31 okb = Button(adding,text="Ok",command=add_ok) 32 cancel_b = Button(adding,text="Cancel",command=adding.destroy) 33 34 hour_entry.grid() 35 minute.grid() 36 chb.grid() 37 okb.grid() 38 cancel_b.grid() 39 40 adding.mainloop() 41def add_ok(): 42 hour_list.append(hour_entry.get()) 43 minute_list.append(minute.get()) 44 45 tmp = str(hour_entry.get()) + ":" + str(minute.get()) 46 47 listbox.insert(END,tmp) 48 49def check_time(): 50 hour = datetime.now().strftime('%H') 51 minute = datetime.now().strftime('%M') 52 53 tk.after(1000,check_time) 54 55 56main_window() 57add_window() 58tk.after(1000,check_time) 59 60tk.mainloop() 61 62

長いですが、これがコードです。
肝心のエラーなのですがこのようなエラーメッセージが出ます。
File "/Users/oooo/Documents/目覚まし時計.py", line 43, in add_ok
hour_list.append(hour_entry.get())
NameError: name 'hour_entry' is not defined

色々試してわかったのですが、ウィジェットを作った関数内でしかその操作ができないようです。
一応関数add_ok()内で作っているのですが、このようなエラーが出て頭がこんがらがっています。
解決方法を教えていただければ幸いです。

ちなみにやりたいことは、ボタンが押された時に二つのテキストボックスの値を取り出して、リストボックスに挿入することです。

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

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

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

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

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

guest

回答2

0

エラーに関しては y_waiwaiさんが書かれている通りで、listboxという変数はmain_window() 内で定義されたローカル変数なので関数外からの使用はできません。

単純にグローバルスコープに変更する事で解決するかとは思うのですが・・・、あまり薦められる方法ではありません。
https://teratail.com/questions/129515

とりあえず今回はListbox Widgetに名前をつけてtk変数から取得する方法で良いのではないでしょうか。

具体的な方法としてはmain_window()関数でListboxを生成する際に

Python

1 listbox = Listbox(name="timelist")

などと適当な名前を設定し、add_ok()関数では

Python

1def add_ok(owner): 2 #前半省略 3 listbox = tk.children['timelist'] 4 listbox.insert(END,tmp)

とWidgetの名前からListbox Widgetを取得します。


【追記】

動作させてみたところ他にも同様のエラーの箇所があるようです。
下記の箇所で同様にhou_entryminute をそれぞれ参照できないとのエラーとなります。
こちらに関しては上と違いWidgetのOwnerが別Windowなので一工夫が必用です。

まず、現状ボタンを生成する際に

Python

1 okb = Button(adding,text="Ok",command=add_ok)

としている箇所を

Python

1 okb = Button(adding,text="Ok",command=lambda : add_ok(adding))

のように変更し、lambdaを使って add_ok()関数の引数としてOwnerとなるWindowを渡すように修正してください。

あとは上と同様に

Python

1def add_ok(owner): 2 hour_entry = owner.children['hour_entry'] #<- Widget名は適当 3 minute = owner.children['minute_entry'] #<- Widget名は適当 4 # 以下省略

のようにすることで、同じWindowにある Entry Widget を取得できるようになるかと思います。

投稿2019/03/01 00:05

編集2019/03/01 00:26
magichan

総合スコア15898

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

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

0

関数の中で定義される変数はローカル変数といって、その関数の中でしか有効ではありません。
関数間でまたがって使用したいなら、グローバル変数にしなければなりません。

投稿2019/02/28 22:27

y_waiwai

総合スコア87719

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問