Reputation: 1090
I want to check if the user has changed any values in tkinter widgets and then prompt to save those values or lose changes.
A lot of applications have 3 buttons at the bottom right of their settings frame OK
, Cancel
, and Apply
where Apply
is disabled until a change has been made. I am imitating this feature in my program.
When I use tk.OptionMenu(command=function)
, by default it sends the current user selection to the function, however I do not need to know the current selection because regardless of what it is, I want to prompt the user to save settings.
Running the program would result in the following error:
TypeError: function() takes 0 positional arguments but 1 was given
A simple workaround I thought of would be to give an arbitrary parameter to function()
like so:
def function(param=None):
value_change.status = True
See Example Code for value_change.status
usage.
However, PyCharm points out that param
is not used and marks it as a weak warning. I don't have any use for the passed value so I can't do much with param
except ignore it and the PyCharm warning as well. There's technically nothing wrong here but I like seeing that green checkmark at the top right of my screen so I came up with another workaround:
def function(param=None):
value_change.status = True if param else False
Both param=None
and if param else False
are redundant since they're only placeholders to make the code run smoothly and not throw any warnings.
Another problem arises when I want to use function()
for other widget commands which do not pass arguments such as tk.Checkbutton(command=function)
and I have to change my code to the following lines which makes the code appear even more redundant than before.
def function(param=True):
value_change.status = True if param else False
Is there a way to not pass an argument through tk.OptionMenu(command=function)
?
Example Code
import time
import tkinter as tk
from threading import Thread
def value_change():
value_change.count = 0
value_change.status = False
print('Has the user changed settings in the past 3 seconds?')
while value_change.status != 'exit':
if value_change.status:
value_change.count += 1
# Reset count if no change after 3 seconds
if value_change.count > 3:
value_change.count = 0
value_change.status = False
print(value_change.status)
time.sleep(1)
def function(param=True):
value_change.status = True if param else False
value_change.count = 0
gui = tk.Tk()
gui.geometry('100x100')
"""Setup OptionMenu"""
menu_options = ['var1', 'var2', 'var3']
menu_string = tk.StringVar()
menu_string.set(menu_options[0])
option_menu = tk.OptionMenu(gui, menu_string, *menu_options, command=function)
option_menu.pack()
"""Setup CheckButton"""
check_int = tk.IntVar()
check = tk.Checkbutton(gui, variable=check_int, command=function)
check.pack()
"""Turn On Thread and Run Program"""
Thread(target=value_change).start()
gui.mainloop()
"""Signal Threaded Function to Exit"""
value_change.status = 'exit'
The above example is a minimal reproduction, I did not include the OK
Cancel
Apply
buttons and their functions as they are not necessary and would only make the code lengthy.
Upvotes: 0
Views: 60
Reputation: 46688
You can use lambda
:
option_menu = tk.OptionMenu(gui, menu_string, *menu_options, command=lambda v: function())
Upvotes: 1