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

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

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

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

Python

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

Q&A

解決済

3回答

6967閲覧

Python tkinterでリセットボタンを作りたい

Colt-Python

総合スコア9

Tkinter

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

Python

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

0グッド

0クリップ

投稿2020/05/05 11:21

編集2020/05/05 11:43

前提・実現したいこと

リセットボタンを実装し,変数をリセットしたい。
リセットボタンを押すと、合計と注文を初期状態に戻したい
具体的にはGOKの値と*_Howの値をリセットし、各表示も消したいです。

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

NameError: name 'clear' is not defined

該当のソースコード

Python3

1import tkinter as tk 2from tkinter import ttk 3import tkinter.font as tkFont 4 5root = tk.Tk() 6root.title("Tech") 7 8 9root.geometry("1024x600") 10 11 12frame1=tk.LabelFrame(root, width=480, height=500, text="メニュー") 13frame1.place(x=0,y=0) 14 15frame2=tk.LabelFrame(root, width=213, height=400, text="注文内容") 16frame2.place(x=780,y=0) 17frame2.grid_propagate(0) 18 19frame3=tk.LabelFrame(root,width=213, height=100, text="合計金額") 20frame3.place(x=780,y=413) 21frame3.grid_propagate(0) 22 23frame4=tk.LabelFrame(root, width=765, height=80, text="Control") 24frame4.place(x=0,y=515) 25frame4.grid_propagate(0) 26 27 28a_notebook = ttk.Notebook(frame1, width=760, height=400) 29tab1 = ttk.Frame(a_notebook) 30 31a_notebook.add(tab1, text = '麺') 32 33a_notebook.grid() 34 35 36UDN_How = 0 37UDN_Var = tk.StringVar(value="") 38SOBA_How = 0 39SOBA_Var = tk.StringVar(value="") 40 41 42GOK = 0 43GOK_Var = tk.StringVar(value="合計" + str(GOK) + "円") 44 45 46def UDNcom(): 47 global UDN_How 48 UDN_How = UDN_How + 1 49 50 global GOK 51 GOK = GOK + 200 52 53 UDN_Var.set("うどん 200円" + str(UDN_How) + "個") 54 GOK_Var.set("合計" + str(GOK) + "円") 55 56 57def SOBAcom(): 58 global SOBA_How 59 SOBA_How = SOBA_How + 1 60 61 global GOK 62 GOK = GOK + 200 63 64 SOBA_Var.set("そば 200円" + str(SOBA_How) + "個") 65 GOK_Var.set("合計" + str(GOK) + "円") 66 67#tab1 68UDN = tk.Button(tab1, command=UDNcom, text="うどん\n¥200") 69UDN.grid() 70 71SOBA = tk.Button(tab1, command=SOBAcom, text="そば\n¥200") 72SOBA.grid() 73 74#Label 75UDN_Lab = tk.Label(frame2, textvariable=UDN_Var) 76UDN_Lab.grid() 77 78SOBA_Lab = tk.Label(frame2, textvariable=SOBA_Var) 79SOBA_Lab.grid() 80 81############################### 82def RSTcom(): 83 clear(GOK) 84 85 86RST = tk.Button(frame4, command=RSTcom, text="リセット") 87RST.grid() 88################################## 89 90 91GOK_Lab = tk.Label(frame3, textvariable=GOK_Var) 92GOK_Lab.grid() 93 94 95root.mainloop()

試したこと

リセットボタンを押した際にGOKをクリアしようとした

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

Win10
Python3
Tkinter
Atom

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

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

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

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

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

Yasumichi

2020/05/05 11:34

いきなり答えを変えてしまうと勉強にならないかもしれないので伺います。 値をリセットしたいのは、GOK だけではないですよね?UDN_How、SOBA_How もリセットしたいですよね。 さらに画面表示も該当部分は消したいのですよね? まず、変数の目的を整理して、追記してみてはいかがですか? あと、clear って何のクリアのつもりで使ってますか?
Colt-Python

2020/05/05 11:53

仰る通りでございます。 GOKと*_Howの値をリセットし、該当部分の画面表示を消したいです。 GOKをリセットするつもりでclear(GOK)と打ち込んでいますが、根本的に間違っているようです
Yasumichi

2020/05/05 11:55

GOK や *_How を初期化する時は、どうしていたか振り返ってみてください。
Colt-Python

2020/05/05 12:14

0や""で置き換えてみましたが初期化されませんでした def RSTcom(): GOK_Lab = "" GOK_Lab = 0 UDN_Lab = "" UDN_Lab = 0
Yasumichi

2020/05/05 12:32

ラベルには、UDN_Var とか、変数と関連付けてませんでしたっけ?
Colt-Python

2020/05/05 13:13

Varは個数の更新用だった気がします
guest

回答3

0

「リセット時に、現在のウィジェットを破棄して再生成する方法」の実装例です。

コードは大幅に変更してる為、
この方法を今のコードへそのまま適応することはできませんが、
メニューが増えた場合等で設計を見直す機会があれば、参考にして見て下さい。

要点は、collections.defaultdict で注文内容を管理してます。(通常の辞書でもいい)
これによりリセット時の処理を、辞書の clear() 呼び出しと、
再描画 (update_itemsメソッド)のみで行えるようになります。

イメージ説明

python

1import tkinter as tk 2from tkinter import ttk 3from collections import defaultdict 4 5MENU = { 6 "UDON": 200, 7 "SOBA": 200, 8} 9 10 11class CartListBox(ttk.Labelframe): 12 def __init__(self, master, *args, **kw): 13 super().__init__(master, *args, **kw) 14 self.data = defaultdict(int) 15 16 def update_items(self): 17 # 以前の要素を破棄 18 for child in self.winfo_children(): 19 child.destroy() 20 21 # 再生成 22 for key, value in self.data.items(): 23 self.create_row(key, value) 24 25 def create_row(self, key, value): 26 frame = ttk.Frame(self) 27 frame.pack() 28 text = "{} {}個 ({}円)".format(key, value, MENU[key]*value) 29 ttk.Label(frame, text=text).pack(side=tk.LEFT) 30 ttk.Button(frame, text="[取消]", command=lambda:self.delete(key)).pack(side=tk.LEFT) 31 32 # 辞書の内容に変化があった場合、update_items() を呼び出し再描画 33 34 def delete(self, key): 35 del self.data[key] 36 self.update_items() 37 38 def add(self, key, value=1): 39 self.data[key] += value 40 self.update_items() 41 42 def reset(self): 43 self.data.clear() 44 self.update_items() 45 46 @property 47 def total(self): 48 # 合計金額の計算 49 return sum(MENU[key] * value for key,value in self.data.items()) 50 51 52def main(): 53 root = tk.Tk() 54 root.minsize(500, 400) 55 56 style = ttk.Style() 57 style.configure("TLabel", font=("", 30)) 58 59 cart = CartListBox(root, text="注文内容", width=600, height=400) 60 cart.pack(fill=tk.BOTH, expand=1) 61 62 def create_menu_button(key): 63 text = "{} {}円".format(key, MENU[key]) 64 button = ttk.Button(root, text=text, command=lambda:cart.add(key)) 65 button.pack(side=tk.LEFT) 66 return button 67 68 button1 = create_menu_button("UDON") 69 button2 = create_menu_button("SOBA") 70 reset_button = ttk.Button(root, text="[Reset]", command=cart.reset) 71 reset_button.pack(side=tk.LEFT) 72 73 totalLabel = ttk.Label(root, text="") 74 totalLabel.pack(side=tk.LEFT) 75 76 def update_total_label(event=None): 77 totalLabel["text"] = "合計金額: {} 円".format(cart.total) 78 79 # XXX: 注文リストの再描画時に、合計金額も再計算 80 def hook_update_func(original_func, additional_func): 81 return lambda: [original_func(), additional_func()] 82 cart.update_items = hook_update_func(cart.update_items, update_total_label) 83 cart.update_items() 84 85 root.mainloop() 86 87if __name__ == '__main__': 88 main()

解説が必要だと思う部分の注釈

python

1# XXX: 注文リストの再計算時に、合計金額も再計算 2def hook_update_func(original_func, additional_func): 3 return lambda: [original_func(), additional_func()] 4cart.update_items = hook_update_func(cart.update_items, update_total_label)

※ 読み難い部分ですが、コードを短くする為に妥協した箇所。
cart.update_items 呼び出し時(辞書の中身に変更があった時)に、
update_total_labelも一緒に読んで貰うように、関数を再構成してます。
複雑になってくると破綻するので、あまりきれいな方法ではありません。

投稿2020/05/05 23:22

編集2020/05/05 23:38
teamikl

総合スコア8664

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

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

Colt-Python

2020/05/24 01:01

理想的な動作ですが、自分の知識では理解が難しいコードなので、もう少し単純化したいです。 そこで取り消しの処理を無くし、リセットの処理のみにしたい場合、どこを削ればよいでしょうか?
teamikl

2020/05/24 04:11

create_row() 内の取消の1行のみです delete() の定義部分も削れますが、 残しても呼び出されないので、特に動作に支障はありません。
guest

0

Tkinterには、HTMLのフォームのような一括でリセットしてくれるような仕組みはないので、
Yasumichi さんが回答で示されてるように、一つづず値を再設定することになります。


余談で、別アプローチですが(紹介のみ)、ウイジェット生成を関数にして置き、
リセット時に、現在のウィジェットを破棄して再生成する方法もあります。
雑な方法ですが、複雑化した状況を一括で戻したい時に使えることも。。

リセットというと、「値のクリア」若しくは「初期値に戻す」ですが、
初期値に戻したい場合は、初期化の時にリセット処理を呼び出すようにしておきます。

投稿2020/05/05 18:17

teamikl

総合スコア8664

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

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

0

ベストアンサー

「質問への追記・修正」で何度かやり取りしてみたので一度、修正案を提示します。

あまりスマートではないかもしれませんが、以下のように修正してみました。

python

1 global UDN_How, SOBA_How, GOK 2 UDN_How = 0 3 SOBA_How = 0 4 GOK = 0 5 UDN_Var.set("") 6 SOBA_Var.set("") 7 GOK_Var.set("")

※takemiさんのご指摘を受け、global 宣言を整理しました。

変数表

変数は以下の内容だと認識しました。

変数名内容
UDN_Howうどんの個数を保持
SOBA_Howそばの個数を保持
GOK合計金額を保持
UDN_Var"うどん 200円?個"というラベルの文字列
SOBA_Var"そば200円?個"というラベルの文字列
GOK_Var"合計?円"というラベルの文字列

投稿2020/05/05 13:17

編集2020/05/06 01:56
Yasumichi

総合スコア1773

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

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

Colt-Python

2020/05/05 14:17

表まで作っていただきありがとうございます リセットの部分は解決したのですがうどんやそばのラベルを上から詰めるにはどうすればいいでしょうか?
Yasumichi

2020/05/05 14:24

注文内容の欄ですか? 上から詰めているように見えるのですが、そちらでスクリーンショットを取って、こうしたいというのを絵で作ることできますか? できれば、別質問にした方が良いかもしれませんが…。
Colt-Python

2020/05/05 15:02

先に押したものが上にくるようにしたいです そばを先におすとそばがうえに来るようにしたいです。
Yasumichi

2020/05/05 15:08

とりあえず、意味は理解しました。夜も更けてきたので明日、考えてみます。
Yasumichi

2020/05/05 15:11

別の質問で起こすと一緒に考えてくれる人が増えるかもしれません。
teamikl

2020/05/05 18:30

別の問題に分けてもらうか、リセットの一環であるなら 質問に条件を追記してもらう方が良さそうですね。 一点だけ補足させていただくと、 グローバル宣言は "global GOK, UDN_How, SOBA_How" の3つのみで済みます。 他のは、変数の指すオブジェクト自体の変化ではなく、中身の値の変化なので変数自体は参照のみ。 グローバル変数であることを明示する為に、敢えて宣言というコードも稀に見かけますが、 例えば、リセット関数内で UDN_Var = tk.StringVar(value="") としても意図した挙動にはならず、 ウィジェットと関連付けされてる Var が参照できなくなるので、 不要なグローバル宣言は出来るだけしない方が安全です。
Yasumichi

2020/05/06 01:40

ご教示、ありがとうございます。正直、tkinter はあまり慣れてないので補足、助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問