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

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

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

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

Tkinter

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

Q&A

解決済

2回答

504閲覧

for文で作成したボタンと同じ場所にラベルを表示させたい

onikudaisuki

総合スコア23

Python 3.x

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

Tkinter

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

0グッド

0クリップ

投稿2022/07/02 14:53

前提

tkinterをクラスで表現するのに挑戦中です。
三つのボタンをfor文で設置し,ボタンをおすとラベルとなるフルーツが一つ抽選されます。

実現したいこと

for文で作成したボタンが押されたらボタンを削除して,消えたボタンの場所にラベルを表示させたいです。

発生している問題

self.result.place(x=self.x1,y=self.y1)とすると,何もラベルが表示されませんでした。
一方,x,yにそれぞれ適当な数字を設定すると,三つボタンをおしてもラベルを表示する場所がかぶってしまいました。
当たり前のことだとわかっていますが,解決法がわかりません。どうかご教授お願い致します。

該当のソースコード

python

1import random 2import tkinter as tk 3class Main(tk.Frame): 4 def __init__(self, master = None): 5 super().__init__(master) 6 self.master.geometry("500x60") 7 self.master.resizable(False,False) 8 self.canvas1 = tk.Canvas(self.master,width=500, height=60, bg="#fafafa") 9 self.canvas1.pack() 10 self.fruits = ["apple", "grape", "orange"] 11 self.x1 = 10 12 self.y1 = 10 13 for i in range(3): 14 self.button1 = tk.Button(master=self.canvas1, text=" 抽選 ", 15 bg="#fafafa", fg="#000000",font=('MS Pゴシック', '17')) 16 self.button1.place(x=self.x1,y=self.y1) 17 self.button1.bind("<ButtonPress>",self.click_button) 18 self.x1 += 165 19 20 def click_button(self,event): 21 event.widget.destroy() 22 self.chusen() 23 self.result = tk.Label(master=self.canvas1, text=self.selected_fruits, 24 bg="#fafafa", fg="#000000",font=('MS Pゴシック', '17')) 25 self.result.place(x=self.x1,y=self.y1) 26 def chusen(self): 27 self.selected_fruits = random.choice(self.fruits) 28 print(self.selected_fruits) 29 30def main(): 31 root = tk.Tk() 32 app = Main(master=root) 33 app.mainloop() 34 35if __name__ == "__main__": 36 main()

試したこと

ボタンを押したときのマウスのポインターの座標を取得すればと思いましたが,それだと毎度ばらばらの位置になってしまうと考え断念しました,

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

win11,python3.10.4

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

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

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

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

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

guest

回答2

0

ベストアンサー

ボタンの座標が保存されていないのが問題です。
ボタン作成時に、それぞれの座標をどこかに保存しておいて、イベント発生時に取り出せばいいと思います。

自分なら、ボタンオブジェクトそのものに保存します。

python

1 self.button1.place(x=self.x1,y=self.y1) 2 self.button1.pos = [self.x1, self.y1]

そしてしておけば、イベント処理の関数のevent内にそのボタンオブジェクトが入っているので参照できます。

python

1 def click_button(self,event): 2 btn_pos = event.widget.pos 3 event.widget.destroy() 4 self.chusen() 5 self.result = tk.Label(master=self.canvas1, text=self.selected_fruits, 6 bg="#fafafa", fg="#000000",font=('MS Pゴシック', '17')) 7 self.result.place(x=btn_pos[0], y=btn_pos[1])

ところで、質問とは直接関係ありませんが、クラスの変数の持ち方がよくないと思います。

ボタン作成時に、self.button1 というインスタンス変数を使っていますが、結局この変数は最後に作ったボタンだけ参照しているので利用価値がありません。後から参照する必要がないのであれば、インスタンス変数にする必要はないのでローカル変数でいいでしょう。インスタンス変数に入れておきたいのであれば、全てのボタンを保持できるようにリストにして保持するようにすればいいでしょう。
下記の例では、button_listに入れていますが、事前に作っておく必要があります。

python

1 for i in range(3): 2 self.button_list.add(tk.Button(...))

同様に、x1, y1 も インスタンス変数になっていますが、最後のボタンの位置を保持している変数になってしまっています。ローカル変数にしてしまうか、上と同様リストなどに保持するのがいいでしょう。ただ、リストに保持するのであれば、先に提案したボタンに保存するのは不要で、このリストから参照すればよくなりますね。

投稿2022/07/02 15:51

TakaiY

総合スコア12745

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

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

onikudaisuki

2022/07/03 04:46

ありがとうございました。できました!
guest

0

ボタンをdestroyで消してから座標を取得しようとしているからだと思うので、
消す前に座標を変数に入れておくかラベルを追加してからボタンを消してみては。
と思ったんでですがそれ以前の問題で、
ラベル配置のためのx1の座標が3回目のself.x1 += 165によって4つ目相当の位置に設定されているからです。
event.widget.winfo_x()でx座標とるのが一番話が早そう

投稿2022/07/02 15:02

編集2022/07/02 15:24
RiaFeed

総合スコア2701

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

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

onikudaisuki

2022/07/03 04:46

回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問