Basically, what I've done is bound a click event to a function. For example:
self.button1.bind("<Button-1>",self.chooseDice)
What I want now is to access the result of chooseDice()
in another function. What is the best way to go about doing that?
class GraphicsInterface:
#we want to initialize the game board here, set up the dice and buttons
def __init__(self):
self.window = Tk()
self.window.geometry("720x500")
#buttons under each die
self.clicked=[] #empty list to collect all the buttons that were clicked (see chooseDice function)
self.button1 = Button(self.window, text="Dice 1", width=13) #create the button object
self.button1.place(x=60, y=160)
#bind button click event to a function (chooseDice())
self.button1.bind("<Button-1>",self.chooseDice)
self.button2 = Button(self.window, text="Dice 2", width=13)
self.button2.place(x=185, y=160)
self.button2.bind("<Button-1>",self.chooseDice)
#using the event as an argument, append the text to the clicked list
def chooseDice(self, event):
self.clicked.append(event.widget.cget('text'))
self.diceList=[] #create a new empty list
for i in range(len(self.clicked)):
self.diceList.append(int(self.clicked[i][5])) #get just the int value of the last character (i.e. the dice number)
self.deactivate(event.widget) #deactivate the button
return self.diceList
You are already doing what you need to do. Your example code sets self.diceList
to some value. Anywhere else in your code you can directly use self.diceList
.
By the way -- you're writing code that is going to be hard to maintain over time. For example, what if you change the dice label to "Dice One" or simply "One" rather than "Dice 1"? Or, as your app progresses you might want graphical images instead of text on the buttons. You'll have to modify the code that parses the button name. You are essentially encoding information in a button label which is not a good idea.
A simple solution, that also makes your chooseDice
method simpler and easier to understand, is to pass in the dice number in the callback. For example:
self.button1.configure(command=lambda btn=self.button1: self.chooseDice(btn, 1))
The above passes two parameters to the chooseDice
method: the button instance (so you can disable it) and the button number (so you don't have to parse the button name to get it)
This also allows you to create your dice in a loop rather than hard-coding multiple copies of the same block of code. Here's a complete working example:
from Tkinter import *
class GraphicsInterface:
def __init__(self):
self.window = Tk()
self.window.geometry("720x500")
self.clicked=[]
self.buttons = []
for n in range(1, 3):
btn = Button(text="Button " + str(n))
btn.configure(command=lambda btn=btn, n=n: self.chooseDice(btn, n))
btn.pack()
self.buttons.append(btn)
btn = Button(text="Go!", command=self.go)
btn.pack()
self.window.mainloop()
def go(self):
print "buttons:", self.clicked
self.reset()
def reset(self):
'''Reset all the buttons'''
self.clicked = []
for button in self.buttons:
button.configure(state="normal")
def chooseDice(self, widget, number):
self.clicked.append(number)
widget.configure(state="disabled")
app = GraphicsInterface()
Finally, some last bits of advice:
Don't use place
, it makes your GUIs harder to create, and they won't react well to changes in window size, changes in font, changes in platform, etc. Use pack
and grid
instead. Also, don't create fixed-width buttons. Again, this is to better handle changes in fonts. There are times when you want fixed width buttons, but it doesn't look like your code has any reason to use them.
Finally, I don't know what you're actually trying to accomplish, but usually if you're using buttons to track state (is this thing pressed or not?) you want to use checkboxes (pick N of N) or radiobuttons (pick 1 of N). You might want to consider switching to those instead of to buttons.
just add a self.result
attribute to your class and set it at chooseDice()
Refactor. Split this into two functions.
One returns the proper result, usable by other objects.
The other is bound to a GUI control, and uses the proper result to activate and deactivate GUI objects.
Indeed, you should always do this. You should always have functions that do normal Python stuff, work correctly without the GUI and can be unit tested without the GUI. Then you connect this working "model" to the GUI.