0

I have a text based adventure which uses tkinter as its GUI, and am trying to create a function which will label buttons with different options, then return which button was pressed. I want to do this so it can be used as a general function for any decision in the game. I can create the buttons, but cannot get the function to return which button was clicked. This is roughly what I have so far:

from tkinter import *
import time

class Main(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        #configuring and placing frame

    def change_1(self):
         self.choice = 1
    ..............
    def change_5(self):
        self.choice = 5

    def userChoice(self, o1, o2, o3, o4, o5, title, cmdlist)# cmdlist if there is less than 5 options
        self.choice = 0
        titleLable = Label(self, text = title)
        #place & config
        button_1 = Button(self, text = o1, command = self.change_1)
        #place and configure buttons
        ..........
        button_5 = Button(self, text = o5, command = self.change_5)
        #place and configure more buttons

        while self.choice not in cmdlist:
            time.sleep(.5)
        return self.choice

root = Tk()

main = Main(root)
cmdlist = [1, 2, 3, 4, 5]
cmd = main.createChoices("Option 1", "Option 2", "Option 3", "Option 4", "Option 5", "Choose an Option", cmdlist)

#here would be something similar to: if cmd == 1: 
                                        do this etc.

root.mainloop()

1 Answer 1

1

There are a couple of things you can do.

I would go with the dynamic approach. If you don't need to reference you buttons after creating them ( eg. don't need to change text or delete etc ) then you can do

def press(self, val):
    self.choice = val

def create_buttons(self):
    btn_text = ('Btn1', 'Btn2', 'Btn3')

    for i, txt in enumerate(btn_text, 1):
        btn = Button(self, text = txt, command = lambda val = i: self.press(val))
        btn.pack()

Here lambda is a function itself that when clicked will call the press function and pass in the value it was given, so for the first button it's 1, second is 2, etc

If your press function will only change self.choice and not do anything else then you can change it to command = lambda val = i: self.choice = val and not need a press function at all

If you will need to reference the button at another time, then you can create a list to append your button objects to link back to using.

Alternatively you can also just do

button_1 = Button(self, text = o1, command = lambda: self.press(1))
..........
button_5 = Button(self, text = o5, command = lambda: self.press(5))

Or again if you only change the value

button_1 = Button(self, text = o1, command = lambda: self.choice = 1)
..........
button_5 = Button(self, text = o5, command = lambda: self.choice = 5)

Some tips as well. Instead of having the function take 5 variables for the button text you can just give it a list or tuple and index it. Also I don't know if your cmdlist has other values besides 1 - 5, but if it doesn't then you don't need a cmdlist and can just do

while self.choice not in range(1, 6): # if it goes from 1 to 5

Finally, I suggest avoiding time.sleep, it does not go well with tkinter since it completely stalls the GUI and the user loses all control over it.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that was helpful, but I'm still having trouble retrieving the value, as any while loop I try and put in seems to stop the GUI from displaying at all
You can't use infinite while loops in tkinter, any processing it has to do stalls the program until it is resolved and being infinite it never will resolve.mainloop is already an infinite loop so you can't have another. I'm not sure what you're trying to do but I think instead of checking the value in the background. Do what you want when the button is clicked inside the function. Alternatively you can use root.after to continuously re-call a function after a set time which can be your checking.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.