Python Tkinker, checkbox append string value to list?
The following code allows me to add/remove France/Italy from a list when clicked on a tkinter checkbox. Rather than passing 0 or 1 to the Add_France function, is it possible to pass through a string "France"? Thanks
My_list = []
root = Tk()
Country_Variable1 = tkinter.IntVar()
Country_Variable2 = tkinter.IntVar()
def Add_France():
if Country_Variable1.get() == 1:
My_list.append("France")
if Country_Variable1.get() == 0:
My_list.remove("France")
print (My_list)
def Add_Italy():
if Country_Variable2.get() == 1:
My_list.append("Italy")
if Country_Variable2.get() == 0:
My_list.remove("Italy")
print (My_list)
check1 = Checkbutton(root, text='France',variable=Country_Variable1, onvalue=1, offvalue=0, command=Add_France)
check2 = Checkbutton(root, text='Italy',variable=Country_Variable2, onvalue=1, offvalue=0, command=Add_Italy)
check1.pack()
check2.pack()
root.mainloop()
Solution 1:
You have control over onvalue
and offvalue
with Checkbutton
, so you can play around with the value that it returns in each state. In the below example, you can see how to make checkbutton based on inputs inside the list(assuming it is a list of strings of characters always):
from tkinter import *
root = Tk()
def process(var,text):
try:
val = int(var.get()) # If not selected it will give 0 as int, which will trigger `else` block
except ValueError:
val = var.get()
if val: # if val is not empty, ie, if val is any selected value
slct_ctry_lst.append(val)
else: # if val is 0
slct_ctry_lst.remove(text) # Remove the corresponding text from the list
print(slct_ctry_lst)
slct_ctry_lst = []
countries = ['France','Italy','China','Russia','India']
for idx,i in enumerate(countries):
var = StringVar(value=" ")
Checkbutton(root,text=i,variable=var,command=lambda i=i,var=var: process(var,i),onvalue=i).grid(row=0,column=idx)
root.mainloop()
Thought it would be easier, but maybe not suitable, with ttk.Combobox
:
def process(e):
val = e.widget.get()
if val in slct_ctry_lst: # If val present inside the list
slct_ctry_lst.remove(val) # Remove it
else:
slct_ctry_lst.append(val)
print(slct_ctry_lst)
slct_ctry_lst = []
countries = ['France','Italy','China','Russia','India']
cbox = ttk.Combobox(root,values=countries,state='readonly')
cbox.pack(padx=10,pady=10)
cbox.set('Select a country')
cbox.bind('<<ComboboxSelected>>',process)
Solution 2:
If the objective here is to make the code reusable for multiple countries, here is initial idea, this can be improved further.
Basically, I am using lambda
expression here to the callback command function and passing the country name.
Created a separate function to create a checkbox which is generic for all the countries.
Now to add a new country to the list all you need to do is add an element to the available_country_list
You can make available_country_list
global or can pass that as an argument to the list_countries
function.
import tkinter
from tkinter import Checkbutton
selected_country_list = []
def select_country(country_name, variable):
global selected_country_list
print(variable)
if variable.get() == 1:
selected_country_list.append(country_name)
elif variable.get() == 0:
selected_country_list.remove(country_name)
print (selected_country_list)
def create_checkbox(parent, country_name):
country_var = tkinter.IntVar()
country_check = Checkbutton(parent, text=country_name, variable=country_var,
onvalue=1, offvalue=0,
command=lambda: select_country(country_name, country_var))
country_check.pack()
def list_countries(root):
available_country_list = ["France", "Italy"]
for country in available_country_list:
create_checkbox(root, country)
def load(root):
# Create list of country checkboxes
list_countries(root)
def start():
root = tkinter.Tk()
root.after(100, load, root) # Enable lazy loading of your components
root.mainloop()
if __name__ == '__main__':
start()