Infinite Loop, not certain as to why - python-3.x

I am trying to take a text based game and make a GUI application with it. It is a number guessing game, where the computer chooses a number between 1 and 100. The user is expected to guess the correct number in the least amount of tries as possible.
My problem is that I am getting into an infinite loop when and I am not sure why or how to correct it.
The application is below:
# Guess My Number
#
# The computer picks a random number between 1 and 100
# The player tries to guess it and the computer lets the player know
# if the guess is too high, too low or right on the money
from tkinter import *
from random import randint
class Application(Frame):
""" A GUI Application for a number guessing game """
def __init__(self, master):
super(Application, self).__init__(master)
self.grid()
self.the_number = randint(1, 100)
self.guess_ent = Entry(self)
self.results = None
self.tries = 1
self.create_widgets()
def create_widgets(self):
Label(self,
text="Welcome to 'Guess My Number'"
).grid(row=0, column=0, columnspan=2, sticky=W+E+N+S)
Label(self,
text="I'm thinking of a number between 1 and 100"
).grid(row=1, column=0, columnspan=2, sticky=W+E+N+S)
Label(self,
text="Try to guess it in as few attempts as possible"
).grid(row=2, column=0, columnspan=2, sticky=W+E+N+S)
Label(self,
text="What is your guess: "
).grid(row=4, column=0, sticky=W)
self.guess_ent.grid(row=4, column=1, sticky=W)
Button(self,
text="Submit Guess",
command=self.guessing
).grid(row=5, column=0, sticky=W)
root.bind("<Return>", self.guessing_a)
self.results = Label(self, text="")
self.results.grid(row=6, column=0, sticky=W+E+N+S)
def guessing(self):
guess = int(self.guess_ent.get())
while guess != self.the_number:
if guess > self.the_number:
self.results.config(text="Lower")
self.guess_ent.delete(0, END)
else:
self.results.config(text="Higher")
self.guess_ent.delete(0, END)
self.tries += 1
if self.tries >= 10:
self.results.config(text="I'm sorry you couldn't guess the "
"number in the appropriate amount "
"of tries. The number I was "
"thinking of was: {}"
.format(self.the_number))
self.results.config(text="You guessed it!. "
"The number I was thinking of was: {}, "
"and it only took you {}, tries"
.format(self.the_number, self.tries))
def guessing_a(self):
self.guessing()
# main
root = Tk()
root.title("Guess My Number")
app = Application(root)
root.mainloop()

The last line of your code root.mainloop() means you already have a while loop in your program. So running a while loop inside an other one the way you did will lead to problems.
So the idea is to take an advantage of the main implicit while loop of your program and use it to increment the number of tries self.tries by one. This is in reality what is naturally when you used the command option of your button and the bind() method for Enter. I think you will understand the solution below easily.
Thus in the below program I modified only guessing() method and ... one last thing: do not forget to inject an event as a parameter to def guessing_a() method otherwise pressing on Enter will raise a TypeError exception.
Program
Here is the full program that works correctly both with pressing the button widget or the Enter keyboard button:
# Guess My Number
#
# The computer picks a random number between 1 and 100
# The player tries to guess it and the computer lets the player know
# if the guess is too high, too low or right on the money
from tkinter import *
from random import randint
class Application(Frame):
""" A GUI Application for a number guessing game """
def __init__(self, master):
super(Application, self).__init__(master)
self.grid()
self.the_number = randint(1, 100)
self.guess_ent = Entry(self)
self.results = None
self.tries = 1
self.create_widgets()
def create_widgets(self):
Label(self,
text="Welcome to 'Guess My Number'"
).grid(row=0, column=0, columnspan=2, sticky=W+E+N+S)
Label(self,
text="I'm thinking of a number between 1 and 100"
).grid(row=1, column=0, columnspan=2, sticky=W+E+N+S)
Label(self,
text="Try to guess it in as few attempts as possible"
).grid(row=2, column=0, columnspan=2, sticky=W+E+N+S)
Label(self,
text="What is your guess: "
).grid(row=4, column=0, sticky=W)
self.guess_ent.grid(row=4, column=1, sticky=W)
Button(self,
text="Submit Guess",
command=self.guessing
).grid(row=5, column=0, sticky=W)
root.bind("<Return>", self.guessing_a)
self.results = Label(self, text="")
self.results.grid(row=6, column=0, sticky=W+E+N+S)
def guessing(self):
if self.guess_ent.get() !='': # if there is a number in the entry widget. You can also improve this by checking if the entered text is a valid number
guess = int(self.guess_ent.get())
if guess > self.the_number:
self.results.config(text="Lower")
self.guess_ent.delete(0, END)
elif guess < self.the_number:
self.results.config(text="Higher")
self.guess_ent.delete(0, END)
else:
self.results.config(text="You guessed it!. "
"The number I was thinking of was: {}, "
"and it only took you {}, tries"
.format(self.the_number, self.tries))
self.tries += 1
if self.tries >= 10:
self.results.config(text="I'm sorry you couldn't guess the "
"number in the appropriate amount "
"of tries. The number I was "
"thinking of was: {}"
.format(self.the_number))
def guessing_a(self, event):
self.guessing()
# main
root = Tk()
root.title("Guess My Number")
app = Application(root)
root.mainloop()

You have a while loop that check while guess != self.number. But, where do you change guess? This condition will always be true -> infinite loop.
You want guess inside the while loop.
Also, in Tk you shouldn't use a while loop, unless you're using threads. This is going to block the GUI. Use the after method instead.

Related

Python tkinter, how to display the message one by one

I'm using tkinter (Python version 3.9) to build an application. In the application, I want the message can be shown one by one according to the progress of the program. However, my application now can only print all the messages together.
The example code is listed as below:
import time
import tkinter as tk
def start():
txt_edit.delete(1.0, tk.END)
for _ in range(10):
txt_edit.insert(tk.END, f"\nmessage should be printed out one by one")
# do something here
time.sleep(0.5)
# job done
window = tk.Tk()
window.title("User Interface")
window.rowconfigure(0, minsize=40, weight=1)
window.rowconfigure(1, minsize=200, weight=1)
window.columnconfigure(1, minsize=200, weight=1)
lbl_1 = tk.Label(master=window, text="Question: ")
lbl_2 = tk.Label(
master=window, text="How to print the text out one by one?", anchor="w"
)
lbl_1.grid(row=0, column=0, sticky="ns")
lbl_2.grid(row=0, column=1, sticky="nsew")
txt_edit = tk.Text(window, relief=tk.SUNKEN, bd=2)
fr_buttons = tk.Frame(window)
btn_open = tk.Button(master=fr_buttons, text="Start", command=start)
btn_open.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
fr_buttons.grid(row=1, column=0, sticky="ns")
txt_edit.grid(row=1, column=1, sticky="nsew")
window.mainloop()
What is the solution to this problem? Thanks!
Calling time.sleep() from tkinter applications isn't a good idea. Your mainloop and time.sleep() are conflicting. Your program works fine, but the changes are not displayed.
The easiest solution is updating the screen. But as I said, you should avoid using time.sleep(). The following solution satisfies your question, though it freezes your program and will not work on a larger application.
def start():
global window
txt_edit.delete(1.0, tk.END)
for _ in range(10):
txt_edit.insert(tk.END, f"\nmessage should be printed out one by one")
# do something here
time.sleep(0.5)
window.update() # show changes
# job done
I would recommend dropping the time module. You can use a timer instead. Also, take into account the while loop. You might want to use multi-threading inside your applications. Here's a simple Timer object and implementation:
class Timer:
# --- Timer object ---
def __init__(self):
self.start_time = None
self.on = False
def start(self):
# start counting
self.start_time = time.time()
self.on = True
def value(self):
# --- return current value ---
if self.on:
return time.time() - self.start_time
else:
return 0
def stop(self):
# --- stop counting ---
self.__init__()
def start():
txt_edit.delete(1.0, tk.END)
msg_count = 0
timer = Timer()
timer.start()
while msg_count != 10:
window.update()
if timer.value() > 0.5:
txt_edit.insert(tk.END, f"\nmessage should be printed out one by one")
timer.start()
msg_count += 1
timer.stop()

Print the difference result between two counters in Python

I have two counters whose results are displayed in a small part of the GUI for reference, but the important data I need is the result of IN minus OUT. For example, if I have 113 IN and 86 OUT, I am going to display those two data but I need to display also the result, 27 (113-86=27).
Screenshot of the app
Given these two counters:
def counter_label_IN(label):
def count():
s.sendall(b'gcounters\x00')
L_IN = next(iter(s.recv(1024)))
print(L_IN)
label_IN.config(text=str(L_IN))
label_IN.after(500, count)
count()
def counter_label_OUT(label):
def count():
s.sendall(b'gcounters\x00')
L_OUT = next(iter(s.recv(1024)))
print(L_OUT)
label_OUT.config(text=str(L_OUT))
label_OUT.after(500, count)
count()
How can I have another timer keeping refreshing the difference between the two?
Also, if the difference is a negative number, I need to display only 0.
EDIT after #j_4321 kind reply.
Thank you so much for the reply. I am a little lost and I guess it is one of those time the reply is right in front of my eyes but it is so bright that I can't see it... The code written gives no error, but the counts displayed in all the labels are zeroes. This is a simplified code, but still you can see the 0:
EDIT 2 after #j_4321 kind reply.
As suggested, I added:
counter_label_IN()
counter_label_OUT()
To the code, which I am pasting here for your consideration. It now gives me this error:
PS C:\Users\lorenzo.amati> & C:/Users/lorenzo.amati/AppData/Local/Programs/Python/Python38-32/python.exe "c:/Users/lorenzo.amati/Desktop/Software PCN/PCN-local-getdata-prova.py"
Traceback (most recent call last):
File "c:/Users/lorenzo.amati/Desktop/Software PCN/PCN-local-getdata-prova.py", line 55, in <module>
counter_label_IN()
File "c:/Users/lorenzo.amati/Desktop/Software PCN/PCN-local-getdata-prova.py", line 38, in counter_label_IN
count()
File "c:/Users/lorenzo.amati/Desktop/Software PCN/PCN-local-getdata-prova.py", line 27, in count
s.sendall(b'gcounters\x00')
OSError: [WinError 10038] An operation was attempted on something that is not a socket
Here is the code:
import socket
import tkinter as tk
import tkinter.ttk as ttk
# Main settings
IP_address = ('172.16.0.103')
root = tk.Tk()
root.title("People Counter")
root.configure(bg="#006bb3")
font1 = "-family {Source sans pro} -size 36 -weight bold"
font2 = "-family {Source sans pro} -size 150 -weight bold"
# use IntVar as counters
counter_IN = tk.IntVar(root)
counter_OUT = tk.IntVar(root)
counter_DIFF = tk.IntVar(root)
# get the sensor data
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP_address,5400))
def counter_label_IN():
def count():
s.sendall(b'gcounters\x00')
L_IN = next(iter(s.recv(1024)))
print(L_IN)
counter_IN.set(L_IN) # update counter IntVar instead of label
# update DIFF counter:
diff = L_IN - counter_OUT.get()
if diff < 0:
diff = 0
counter_DIFF.set(diff)
label_IN.after(500, count)
count()
def counter_label_OUT():
def count():
s.sendall(b'gcounters\x00')
L_OUT = next(iter(s.recv(1024)))
print(L_OUT)
counter_OUT.set(L_OUT) # update counter IntVar instead of label
diff = counter_IN.get() - L_OUT
if diff < 0:
diff = 0
counter_DIFF.set(diff)
label_OUT.after(500, count)
count()
s.close()
counter_label_IN()
counter_label_OUT()
# In/Out Informations display on top
FrameTOP = tk.Frame(root, bg="#006bb3", borderwidth="0")
FrameTOP.grid(row=0, column=0, columnspan=4, sticky='nsew')
Label_RTC_IN = tk.Label(FrameTOP, anchor='w',bg="#006bb3", fg='white',justify='left', text='Realtime count of people IN:')
Label_RTC_OUT = tk.Label(FrameTOP, anchor='w',bg="#006bb3", fg='white',justify='left', text='Realtime count of people OUT:')
label_IN = tk.Label(FrameTOP, textvariable=counter_IN, anchor='w',bg="white",fg="black", justify='left', relief='sunken', borderwidth="2")
label_OUT = tk.Label(FrameTOP, textvariable=counter_OUT, anchor='w',bg='white', fg='black', justify='left', relief='sunken', borderwidth="2")
Label_RTC_IN.grid(row=0, column=0, padx=10, pady=10)
label_IN.grid(row=0, column=1, padx=10, pady=10)
Label_RTC_OUT.grid(row=0, column=2, padx=10, pady=10)
label_OUT.grid(row=0, column=3, padx=10, pady=10)
# Frame in which to put the differential data of people inside
FrameCENTRAL = tk.Frame(root, bg="#006bb3",borderwidth="0")
FrameCENTRAL.grid(row=1, column=0, pady=50, columnspan=4,) #sticky='nsew')
TitleCentral = tk.Label(FrameCENTRAL,anchor='w', bg="#006bb3", fg='white', font=font1, text='''People Inside''')
TitleCentral.grid(row=0, column=0, padx=10, pady=10)
label_DIFF = tk.Label(FrameCENTRAL, textvariable=counter_DIFF, font=font2, bg="#006bb3", fg='white', anchor='center')
label_DIFF.grid(row=1, column=0, padx=10, pady=10)
# IP Informations
FrameBOTTOM = tk.Frame(root, bg="#006bb3", borderwidth="0")
FrameBOTTOM.grid(row=2, column=0, columnspan=4, sticky='nsew')
Label_IP_ADDRESS = tk.Label(FrameBOTTOM,anchor='w',bg="#006bb3",fg='white',text='''People counter sensor locally connected to local IP address:''')
Label_IP = tk.Label(FrameBOTTOM,anchor='w',bg="#006bb3",fg='white',text=(IP_address))
Label_IP_ADDRESS.grid(row=0, column=0, padx=10, pady=10)
Label_IP.grid(row=0, column=1, padx=10, pady=10)
# Closing button
close = tk.Button(FrameBOTTOM, bg="#006bb3",fg='white',text='Stop and close', width=16, command=root.destroy)
close.grid(row=0, column=3, padx=10, sticky='e')
root.mainloop()
Screenshot of the app after the modification, showing all 0
You can use IntVar as the IN, OUT and DIFF = IN - OUT counters and use the textvariable option of the Label to automatically update the text when updating the counters. In the counter_label_...() functions, the IntVar value will be updated instead of updating the label's text.
import tkinter as tk
root = tk.Tk()
# use IntVar as counters
counter_IN = tk.IntVar(root)
counter_OUT = tk.IntVar(root)
counter_DIFF = tk.IntVar(root)
# use textvariable to keep the labels updated
label_IN = tk.Label(root, textvariable=counter_IN)
label_OUT = tk.Label(root, textvariable=counter_OUT)
label_DIFF = tk.Label(root, textvariable=counter_DIFF)
# database polling
def counter_label_IN():
def count():
s.sendall(b'gcounters\x00')
L_IN = next(iter(s.recv(1024)))
print(L_IN)
counter_IN.set(L_IN) # update counter IntVar instead of label
# update DIFF counter:
diff = L_IN - counter_OUT.get()
if diff < 0:
diff = 0
counter_DIFF.set(diff)
label_IN.after(500, count)
count()
def counter_label_OUT():
def count():
s.sendall(b'gcounters\x00')
L_OUT = next(iter(s.recv(1024)))
print(L_OUT)
counter_OUT.set(L_OUT) # update counter IntVar instead of label
diff = counter_IN.get() - L_OUT
if diff < 0:
diff = 0
counter_DIFF.set(diff)
label_OUT.after(500, count)
count()
# start monitoring the database
counter_label_IN()
counter_label_OUT()

How can I print the values of a Entry() in tkinter?

Im just simply trying to print the values of the entry fields and it tells me its not defined. I been looking online for a long while now. The lastest thing that I tried was adding self as a parameter of add_student but that didn't work.
This is the code
from tkinter import *
class window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.widgets()
def add_student(self):
print(f"Student's name (first, last): {self.fname_textbox}, {self.lname_textbox}")
def widgets(self):
self.master.title("Student Test Score & Grade")
self.master.minsize(200,200)
""" Labels """
# First name
self.fname_label = Label(root, text='First Name: ')
self.fname_label.grid(row=0, column=0, padx=5, pady=5)
# Last Name
self.lname_label = Label(root, text='Last name: ')
self.lname_label.grid(row=1, column=0, padx=5, pady=5)
""" Entry boxes """
# First Name
self.fname_textbox = Entry(root, width=30)
self.fname_textbox.grid(row=0, column=1, padx=5)
# Last name
self.lname_textbox = Entry(root, width=30)
self.lname_textbox.grid(row=1, column=1, padx=5)
""" Buttons """
# Add Button
self.add_btn = Button(root, text="Add Student", command=self.add_student).grid(row=4, column=2, padx=2, pady=2)
if __name__=="__main__":
root = Tk()
root.resizable(width=False, height=False)
app = window(root)
root.mainloop()
It prints this
Student's name (first, last): .!entry, .!entry2
Instead of: Student's name (first, last): John, Doe
What does this mean?
You need to get the value of the entries in order to use them in your print statement
You do this by putting:
firstname = self.fname_textbox.get()
lastname = self.1fname_textbox.get()
before you print and using these values in your print statement.
Ah, Try something like this:
def __init__(self, master):
self.nameEntry = Entry(master)
self.contents = StringVar()
self.nameEntry["textvariable"]=self.contents
self.nameEntry.pack()
self.nameEntry.grid(row=0,column=1)
self.buttonSave = Button(master,text="Save",command=self.save).grid(row=9,columnspan=2, sticky=W+E+N+S)
def save(self):
print self.nameEntry.get()

restarting a mainloop in tkinter

I'm new to Python and Tkinter. Here is a game I made for practice with GUIs. The problem I am having is when restarting a new game the code allows the loser to give the first guess. This is an unintended plus that I can't explain. My code is intended to give player 1 the first guess always, but that doesn't happen. I have done my due diligence and think the problem is in the transition between the reset_game method and the player_guess method.
Please describe why my code is not giving player1 the first guess when restarting the game.
If there are any comments as to format, structure, DRY issues, etc. I would appreciate those also.
''' 2 player guessing game with GUI'''
from tkinter import *
from random import randint
import tkinter.messagebox
# create window
root = Tk()
root.title('2 Player Guessing Game')
target_number = randint(1, 100)
message = StringVar()
current_player = ''
# reset target number for a new game
def reset_target_number():
global target_number
target_number = randint(1, 100)
# sets current player variable
def set_current_player(num):
global current_player
current_player = num
# gets player's guess and toggles turn back and forth. passes guess to game_play method
def player_guess():
if p1_entry.get():
print(target_number)
guess = int(p1_entry.get())
set_current_player(1)
game_play(guess)
p1_entry.delete(0, END)
p1_entry.config(state=DISABLED)
p2_entry.config(state=NORMAL)
p2_entry.focus_set()
#print(current_player + ' should be 1')
else:
guess = int(p2_entry.get())
set_current_player(2)
game_play(guess)
p2_entry.delete(0, END)
p2_entry.config(state=DISABLED)
p1_entry.config(state=NORMAL)
p1_entry.focus_set()
#print(current_player + ' should be 2')
# evaluates the guess and returns a message to the message_label. also, calls congrats method when a player has
# guessed correctly
def game_play(guess):
if guess == target_number:
display_message('Winner!')
congrats(current_player)
elif guess < target_number:
display_message('Too Low')
print(current_player, ' is low')
else:
display_message('Too High')
print(current_player, ' is high')
# displays appropriate message in message_label
def display_message(result):
message.set(result)
# opens message box to declare winner. Gives option to exit or play again
def congrats(player_num):
if player_num == 1:
winner = "Player 1"
else:
winner = 'Player 2'
answer = tkinter.messagebox.askquestion('Congratulations', winner + ' is the WINNER!! \n Would you like to play again?')
if answer == 'no':
root.quit()
else:
reset_game()
def reset_game():
reset_target_number()
message = StringVar()
set_current_player(0)
#print(target_number, message, current_player)
p2_entry.delete(0, END)
p1_entry.delete(0, END)
p2_entry.config(state=DISABLED)
#print('Did this run?')
p1_entry.config(state=NORMAL)
#print('Did this also run?')
p1_entry.focus_set()
# create instruction widgets
instruc_label = Label(root, text='Game Instructions')
instruc_label.grid(row=0, column=0, padx=2, pady=2, sticky=W)
instructions = Label(root, text="Players will take turns guessing the mystery number. The first player to guess correctlyl wins! The other player doesn't win: but that doesn't mean the other player is a loser. It just means that that player did not win this time. No amount of failures determines whether a person is a loser. It is a person's attitude and character towards their failures that determines a winner and a loser.", wraplength=490, justify=LEFT)
instructions.grid(row=1, column=0, columnspan=3, padx=5, pady=5)
# create game play widgets
p1_label = Label(root, text='Player 1')
p1_label.grid(row=2, column=0)
p1_entry = Entry(root, font='Helvetica 44 bold', fg='black', bg='lightyellow', relief=SUNKEN, width=4, state=NORMAL, justify=CENTER)
p1_entry.grid(row=3, column=0)
p1_entry.focus_set()
message_label = Label(root, textvariable=message, fg='white', bg='darkgreen', relief=GROOVE, height=10, width=20)
message_label.grid(row=2, column=1, rowspan=2)
p2_label = Label(root, text='Player 2')
p2_label.grid(row=2, column=2)
p2_entry = Entry(root, font='Helvetica 44 bold', fg='black', bg='lightyellow', relief=SUNKEN, width=4, state=DISABLED, justify=CENTER)
p2_entry.grid(row=3, column=2)
# create submit button to enter guesses
submit = Button(root, text='Submit', width=20, command=player_guess)
submit.grid(row=4, columnspan=3, pady=5, padx=5)
root.mainloop()
Mahalo!
In player_guess, winner decided in game_play.
If there is a winner, you are resetting the game with reset_game but your code continues after game_play returns and changes states of entries. game_play should be the last thing player_guess should do.
def player_guess():
if p1_entry.get():
....
game_play(guess)
else:
....
game_play(guess)
or just move game_play out of if-elses since you are calling it either way.
def player_guess():
if p1_entry.get():
....
guess = int(p1_entry.get())
else:
....
guess = int(p2_entry.get())
game_play(guess)

python tkinter.Radiobutton can't get value

I'm writing a python code with tkinter (python3) but I have some problems. I have two classes _MainScreen and _RegisterScreen (this last is nested in _MainScreen). In _RegisterScreen I had implemented a simple question with tkinter.Radiobutton (choose your sex: male, female). The idea is to catch the user selection, but when I run the script, the value assigned to the variable is empty (""). However, if I run the class _RegisterScreen alone, it works. I hope you can show me where is my error. Thanks in advance.
Here is an abstraction (32 lines) of my code (250 lines):
import tkinter
class _MainScreen(tkinter.Frame):
def __init__(self):
self.root = tkinter.Tk()
self.new_account(self.root)
self.root.mainloop()
def new_account(self, frame):
tkinter.Button(frame, text="Create new account",
command=self.create_new_account).pack(anchor="center", pady=(0,15))
def create_new_account(self):
_RegisterScreen()
class _RegisterScreen(tkinter.Frame):
def __init__(self):
self.root = tkinter.Tk()
tkinter.Label(self.root, text="Sex").grid(row=1, padx=(0,10), sticky="w")
self.sex_option = tkinter.StringVar()
tkinter.Radiobutton(self.root, text="Male", variable=self.sex_option,
value="Male", command=self._selected).grid(row=1, column=1)
tkinter.Radiobutton(self.root, text="Female", variable=self.sex_option,
value="Female", command=self._selected).grid(row=1, column=2)
tkinter.Button(self.root, text="Submit",
command=self._login_btn_clickked).grid(row=3, columnspan=4, pady=20)
self.root.mainloop()
def _login_btn_clickked(self):
sex = self._selected()
print(sex)
def _selected(self):
return self.sex_option.get()
_MainScreen()
#_RegisterScreen() # comment the above line and uncomment this line
# to test the _RegisterScreen object alone.
After doing some research on how tkinter's RadioButton widget works, I believe I have a solution to your problem:
Here's your new _RegisterScreen function:
class _RegisterScreen(tkinter.Frame):
def __init__(self):
self.gender = "NA" #Variable to be changed upon user selection
self.root = tkinter.Tk()
tkinter.Label(self.root, text="Sex").grid(row=1, padx=(0,10), sticky="w")
self.sex_option = tkinter.StringVar()
#This Radiobutton runs the setMale function when pressed
tkinter.Radiobutton(self.root, text="Male", variable=self.sex_option,
value="Male", command=self.setMale).grid(row=1, column=1)
#This Radiobutton runs the setFemale function when pressed
tkinter.Radiobutton(self.root, text="Female", variable=self.sex_option,
value="Female", command=self.setFemale).grid(row=1, column=2)
tkinter.Button(self.root, text="Submit",
command=self._login_btn_clickked).grid(row=3, columnspan=4, pady=20)
self.root.mainloop()
def _login_btn_clickked(self):
sex = self.gender #gets the value stored in gender and assigns it to sex
print(sex)
def setMale(self):
self.gender="Male" #sets gender to Male
def setFemale(self):
self.gender="Female" #sets gender to Female
Ultimately, you want to run 2 separate functions for either RadioButton.
When the Male Radiobutton gets clicked, it runs the setMale function.
When the Female Radiobutton gets clicked, it runs the setFemale function.
I believe you were confused about what RadioButton's variable and value attributes actually are (as was I before looking further into this).
I learned more about what those those do in this video: https://www.youtube.com/watch?v=XNF-y0QFNcM
I hope this helps! ~Gunner

Resources