Reputation: 1063
I have a for
loop that is meant to run through a list, display some items in tkinter, wait for a button to be pushed, and then store some Entry
and Checkbutton
data. The code below is a MRE of the basics of what I'm trying to do. In the case below, when the Button
is hit, I want to return to the loop_function
and gather the variables from the button_function
.
I thought perhaps using something like lambda: continue
or lambda: return
might bring it back to the first function, but those throw errors.
Any ideas?
from tkinter import *
class TestClass(Frame):
def __init__(self, parent=None):
self.parent = parent
Frame.__init__(self)
self.main = self.master
self.f = Frame(self.parent)
self.f.pack()
(Button(self.f, text='Start',
command = self.loop_function)
.grid(column=0, row=0, padx=10, pady=10))
def loop_function(self):
name_list = ['Luke', 'Han', 'Leia', 'Chewie']
for n in name_list:
self.button_function(n)
force_user = self.fu.get()
side = self.sd.get()
print(n, force_user, side)
def button_function(self, n):
self.fu = IntVar(value=1)
self.sd = StringVar(value='rebel')
self.fu_e = Checkbutton(self.f, variable=self.fu)
self.sd_e = Entry(self.f, textvariable=self.sd)
col = 0
lbl_list = ['Name', 'Force User?', 'Side']
for l in lbl_list:
(Label(self.f, text=l, width=11, anchor=W)
.grid(column=col, row=0, padx=10, pady=10))
col += 1
(Label(self.f, text=n, width=11, anchor=W)
.grid(column=0, row=1, padx=5))
self.fu_e.grid(column=1, row=1)
self.sd_e.grid(column=2, row=1)
(Button(self.f, text='Save',
command = lambda: print('WAIT HERE!!'))
.grid(column=1, row=2, padx=10, pady=10))
if __name__ == '__main__':
root=Tk()
ui = TestClass(root)
ui.pack()
root.mainloop()
Upvotes: 1
Views: 190
Reputation: 2516
I think the following code does what you want to do. After clicking on the button Start the user gets a dialog where she can enter properties of the first user Luke. By clicking on the button Save the entered data is stored in some way. Then the properties of the next user (Han) can be edited.
A for loop is not the correct approach here. Instead we want to listen for the click events of the start and save buttons. In my solution, when the user clicks Start, the event handler pick_next_player
is being called. This method always picks the next
element from an iterator that I wrapped around name_list
. Then the GUI elements are being rendered with your button_function
.
The event handler save_action
listens to the click event of the Save button. It collects the values that the user entered, stores it into self.results
and displays the next player by calling pick_next_player
.
When the last player has been saved, this script just prints a line 'finished ...' to the console. I assume you are going to stop the script or close the dialog there. But this is of course up to you.
from tkinter import *
class TestClass(Frame):
def __init__(self, parent=None):
self.parent = parent
Frame.__init__(self)
self.main = self.master
self.f = Frame(self.parent)
self.f.pack()
(
Button(self.f, text='Start', command=self.pick_next_player)
.grid(column=0, row=0, padx=10, pady=10)
)
self.name_list = ['Luke', 'Han', 'Leia', 'Chewie']
self.name_iter = iter(self.name_list)
self.results = []
self.current_name = None
def pick_next_player(self):
try:
self.current_name = next(self.name_iter)
except StopIteration:
print(f"finished: {self.results}")
return
self.button_function()
def button_function(self):
self.fu = IntVar(value=1)
self.sd = StringVar(value='rebel')
self.fu_e = Checkbutton(self.f, variable=self.fu)
self.sd_e = Entry(self.f, textvariable=self.sd)
col = 0
lbl_list = ['Name', 'Force User?', 'Side']
for l in lbl_list:
(Label(self.f, text=l, width=11, anchor=W)
.grid(column=col, row=0, padx=10, pady=10))
col += 1
(
Label(self.f, text=self.current_name, width=11, anchor=W)
.grid(column=0, row=1, padx=5)
)
self.fu_e.grid(column=1, row=1)
self.sd_e.grid(column=2, row=1)
(
Button(self.f, text='Save', command=self.save_action)
.grid(column=1, row=2, padx=10, pady=10)
)
def save_action(self):
force_user = self.fu.get()
side = self.sd.get()
print(f"saving {self.current_name}, {force_user}, {side}")
self.results.append({'name': self.current_name, 'force': force_user, 'faction': side})
self.pick_next_player()
if __name__ == '__main__':
root = Tk()
ui = TestClass(root)
ui.pack()
root.mainloop()
Upvotes: 1