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
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.
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 useself.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: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:
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. Usepack
andgrid
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 atchooseDice()