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

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

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

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

Tkinter

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

button

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

Python

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

Q&A

解決済

1回答

7090閲覧

【Python】tkinter.Buttonを複数個配置した場合のクリック時動作に関する質問

takataka_11

総合スコア2

Python 3.x

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

Tkinter

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

button

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

Python

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

0グッド

0クリップ

投稿2020/05/24 03:04

前提・実現したいこと

複数個のボタンを画面に配置、各ボタンにはそれぞれ同じようなクリック時の動作を与える
田中のボタンを押せば100,長谷川を押せば63が返ってくるボタンを作成したいです

実際に作成しているプログラムはソースコードのものよりも少し複雑になっているのですが、こちらに示すソースコードでも同様の問題が発生しています

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

エラーメッセージはありません
どのボタンを押してもprintされるのは72です

該当のソースコード

python3.7

import tkinter as tk

class Application(tk.Frame):
def init(self,master=None):
super().init(master)
master.title("タイトル")
master.geometry("300x300")
self.pack()
self.create_widgets()

ボタンの配置 def create_widgets(self): self.datalist = [["田中","100"],["長谷川","63"],["横川","67"],["三宅","72"]] for self.data in self.datalist: self.button = tk.Button(self,text=self.data[0],command= lambda:self.get_data(self.data[1])) self.button.pack() ボタンクリック時の動作 def get_data(self,A): print(A)

def main():
root = tk.Tk()
app = Application(master = root)
app. mainloop()

if name == "main":
main()

試したこと

def get_data を def create_widgetsの中に入れてみましたが同じ問題が発生しました
ボタンクリック時に渡す引数Aがうまくいってないように思えますが、調べても解決方法がわかりませんでした

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

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

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

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

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

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

guest

回答1

0

ベストアンサー

python

1for self.data in self.datalist: 2 self.button = tk.Button(self,text=self.data[0],command= lambda:self.get_data(self.data[1]))

問題の原因は、lambda 式内のコードが、ボタンクリック時に self.data[1] の値を所得する点で、
データ部分は、for で回されるので、必ず最後の要素が使われることになります。

※ ループ文の中で lambda やクロージャを使う場合の注意点として知られている現象です。
公式FAQ ループの中で異なる値で定義されたラムダ式が、同じ値を返すのはなぜですか?

functools.partial を使うと、command設定時に値を確定できるので解消できます。

python

1# NOTE: 事前に import functools 2 3for name,score in self.datalist: 4 button = tk.Button(self, 5 text=name, 6 command=functools.partial(self.get_data, score)) 7 button.pack()

投稿2020/05/24 04:36

編集2020/05/24 04:42
teamikl

総合スコア8664

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

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

takataka_11

2020/05/24 05:14

ありがとうございます! lambdaについて全く理解していなかったのですが、そうなっていたんですね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問