Reputation: 59
So I know what the problem is, I just don't know how to fix it: self.health gets stored in the variable once and doesn't re-read after that. I've tried using: @property. But I only just learnt about @property yesterday, so either 1: I'm not using it properly, or 2: it can't be used in this situation.
import tkinter as tk
class button_health:
def __init__(self):
self.health = 5
def hit(self, event):
self.health -= 1
bob = button_health()
window = tk.Tk()
button = tk.Button(window, text = bob.health #I want this to update)
button.bind("<Button-1>", bob.hit)
button.pack()
window.mainloop()
What I'm aiming for is for the code to produce a simple tkinter button on screen which starts off saying "5", then when you click it, says "4", then click "3" etc.
Upvotes: 0
Views: 2196
Reputation: 87074
Use a Tkinter IntVar
variable to track changes to the health value. Hook that variable up to the button label using the textvariable
attribute.
import tkinter as tk
class button_health:
def __init__(self, health=5):
self.health = tk.IntVar()
self.health.set(health)
def hit(self, event=None):
if self.health.get() >= 1: # assuming that you can't have negative health
self.health.set(self.health.get() - 1)
window = tk.Tk()
bob = button_health(8)
button = tk.Button(window, textvariable=bob.health, command=bob.hit)
#button = tk.Button(window, textvariable=bob.health)
#button.bind('<Button-1>', bob.hit)
button.pack()
window.mainloop()
Another way is to create your own button class as a subclass of Button
and hook up an IntVar
as a member of the class. This way you can easily create multiple independent buttons with different health values:
import tkinter as tk
class HealthButton(tk.Button):
def __init__(self, window, health=5, *args, **kwargs):
self.health = tk.IntVar()
self.health.set(health)
super(HealthButton, self).__init__(window, *args, textvariable=self.health, command=self.hit, **kwargs)
def hit(self):
if self.health.get() >= 1:
self.health.set(self.health.get() - 1)
window = tk.Tk()
buttons = [HealthButton(window, i) for i in range(10,15)]
for b in buttons:
b.pack()
window.mainloop()
Upvotes: 1
Reputation: 33714
There is an argument called command
in tk.Button
. Binding the button-1 to a function isn't the best way to check if the user clicked the button. And even if you used bind, it should be binded to a function, not a class.
To change a button's text, you can set button['text']
to something.
import tkinter as tk
def button_health():
global health
health -= 1
button['text'] = str(health)
health = 5
window = tk.Tk()
button = tk.Button(window, text = health , command = button_health)
button.pack()
window.mainloop()
You can also avoid using a global
statement by doing this:
import tkinter as tk
def button_health(but):
but.health -= 1
but['text'] = str(but.health)
window = tk.Tk()
button = tk.Button(window)
button.health = 5
button['text'] = str(button.health)
button['command'] = lambda: button_health(button)
button.pack()
window.mainloop()
another advantage for doing it this way is that it can keep the health of the button independent, so if you have multiple buttons, this will keep the counters for all the buttons different.
Upvotes: 1
Reputation: 243947
Use button['text']
or button.config(text={text})
class button_health:
def __init__(self):
self.health = 5
def hit(self, event):
self.health -= 1
button['text'] = str(self.health)
or
class button_health:
def __init__(self):
self.health = 5
def hit(self, event):
self.health -= 1
button.config(text= str(self.health))
Upvotes: 1