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

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

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

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

Tkinter

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

button

HTMLで用いる<button>タグです。

Q&A

解決済

3回答

1256閲覧

Python tkinterでデスクトップ自動販売機を作りたいのですが、ボタンがうまく作れません。

HideBa

総合スコア8

Python 3.x

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

Tkinter

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

button

HTMLで用いる<button>タグです。

0グッド

0クリップ

投稿2019/08/20 15:11

前提・実現したいこと

Python初学者で、初めてのプログラミングとしてtkinterを使い、デスクトップ自動販売機を作りたいと思っています。
環境:windows10, Python 3.7、tkinterを使っています。

まず、それぞれの飲み物の名前をKey、値段と在庫数のリストをValueとしてディクショナリを作りました。
それぞれの飲み物のボタンオブジェクトを生成し、そのコマンドとして、引数に飲み物名を渡し、飲み物を買う機能としてchoose_drinkメソッドを実行したいと思っています。
しかし、このボタンオブジェクトを作るコードでエラーが出ており、解決できません。
まだ初心者なので、そもそもの理解が間違っていることもあるかもしれませんが、教えていただけるとありがたいです。

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

File ".\test2.py", line 27, in main btn_sportsdrink = tk.Button(self.master, text = "sportsdrink:{}".format(self.dict["sportsdrink"][0]), command = self.choose_drink("sportsdrink"), anchor = "c", justify = "center")

該当のソースコード

test.py

1import tkinter as tk 2 3class Application(tk.Frame): 4 def __init__(self,master): 5 super().__init__(master) 6 #出てくる画面のサイズを指定します 7 master.geometry("600x800") 8 #出てくる画面の背景色を指定します 9 master.configure(background='red') 10 self.message = "" 11 self.input_sum = 0 12 self.purchased_cola = 0 13     #ここでディクショナリをつくる 14 self.dict = {"cola":[120, 20], "sportsdrink":[150, 10], "zero":[140, 24], "orange":[130, 40], "tea":[100, 19], "soda":[200, 10], "apple":[170, 10], "melonsoda":[110, 20]} 15 16 def main(self): 17 self.image1 = tk.PhotoImage(file = "./img/drink1.png").subsample(4) 18 tk.Label(self.master, image = self.image1, bg="black").place(x = 25, y = 50) 19# ここでボタンを作る 20# ここのボタンでは、 21 btn_sportsdrink = tk.Button(self.master, text = "sportsdrink:{}".format(self.dict["sportsdrink"][0]), command = self.choose_drink("sportsdrink"), anchor = "c", justify = "center") 22 btn_sportsdrink.place(x = 60, y = 210) 23 24 def choose_drink(self, drink): 25 if self.input_sum - self.dict[drink][0] > 0: 26 self.input_sum -= self.dict[drink][0]

試したこと

  • text = "sportsdrink:{}".format(self.dict["sportsdrink"][0])の部分んの構文が違うのかと思い調べたが、dictのKeyとしてsportsdrinkというドリンク名を入れ、Valueのインデックス0に値するドリンクの金額をformatを使ってTextに渡しているため問題ないはず?
  • self.choose_drink("sportsdrink")の部分で、引数の受け渡しの際に型が違っているのかと考えたが、str形で引数を渡し、choose_drink(self, drink)がdictのKeyもstr型であるため大丈夫そう?

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

  • windows10
  • python 3.7
  • tkinter
  • エディタ:VScode

初歩的なミスかもしれませんが、初心者のため原因が分からず躓いています。
どなたか教えていただけると助かります。よろしくお願いします。

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

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

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

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

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

meg_

2019/08/20 15:18

何のエラーか分からないのですが、エラーメッセージ全文掲載ください。
HideBa

2019/08/22 12:44

助けていただき本当にありがとうございました。lambdaを使うことで解決することができました。
guest

回答3

0

tk.Button()command パラメータにはボタンが押されたときに処理される関数(今回の場合はインスタンスメソッド) 自体を渡す必要があります。
一般的には

Python

1class App(): 2 def f(self): 3 # ボタンを押されたときの処理 4 pass 5 6 def main(self): 7  tk.Button(self.master, text="Button", command=self.f)

のようにボタンが押されたときの処理を記述します。

command=self.f の箇所に () が無いことを注意してください。

この部分を

 tk.Button(self.master, text="Button", command=self.f())

のように()付きで記述しますと
『最初にf関数が呼ばれ、その戻り値(None)がcommandパラメータに設定される』
という動作となりますので場合によってはエラーを引き起こします。

で、今回のようにボタンが押されたときの関数に引数を渡したい場合ですが、meg_さんが回答されております通り、lambda を使うのが一般的ですかね。

Python

1class App(): 2 # 引数をとる関数 3 def f(self, arg): 4 # ボタンを押されたときの処理 5 6 def main(self): 7  tk.Button(self.master, text="Button", command=lambda: self.f("引数"))

投稿2019/08/20 23:53

magichan

総合スコア15898

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

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

HideBa

2019/08/22 12:48

具体的な例で解説いただき本当にありがとうございます。lambdaを使うことで、無事解決しました。ありがとうございました。
guest

0

qt designer を使うのはどうですか
最初に自動販売機のuiだけは作っておいて
機能面だけ自分で作るのはどうでしょうか

tkinterではなくpyqtになってしまいますが

投稿2019/08/20 22:27

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

HideBa

2019/08/22 12:46

ありがとうございます。まだ初心者なので、pyqtを知りませんでした。学習を進める中で、そちらも試してみます。
guest

0

ベストアンサー

引数を与えたい場合にはlambdaを使うと良いようです。

command=lambda:function(args)

投稿2019/08/20 15:30

meg_

総合スコア10580

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

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

HideBa

2019/08/22 12:47

ありがとうございました。lambdaを使うことで、引数を渡し実装することができました。本当に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問