I cannot load a checkbox value from a file and have it correctly check the checkbox when the value is 1.
With the code below you can check a box and save it to a file. Clicking Load will load that value into a second variable, convert it to Int and create a checkbox linked to its value, but it will never generate already checked, even when the value of it's variable is 1 as shown by the print command. What am I doing wrong?
Window = Tk()
var = IntVar()
LoadVarTemp = 0
LoadVar = IntVar()
def SaveIt():
YesVar = var.get()
with open("config.txt", "w") as configfile:
configfile.write(str(YesVar))
def LoadIt():
with open("config.txt") as file:
content = file.readlines()
content = [x.strip() for x in content]
LoadVarTemp = content[0]
LoadVar = int(LoadVarTemp)
print(LoadVar)
Checkbutton(Window, text="Loaded", variable=LoadVar).grid(row=1)
YesCheck = Checkbutton(Window, text="Yes?", variable = var).grid(row=0)
SaveButton = Button(Window, text="Save", command=SaveIt).grid(row=2)
LoadButton = Button(Window, text="Load", command=LoadIt).grid(row=3)
Window.mainloop()
Related
Im trying to check a checkbox and delete both 'checked box' and 'label' with upper button. They are both created in a loop from the same list.
I've tried to build a dictionary with 'buttons' as key and 'result_of_checkboxes' as value and destroy key if value is different from ''. It doesnot work. If buttons are keys, why can't I destroy them? What is the correct approach?
Thanks in advance!
from tkinter import *
root = Tk()
root.geometry('400x400')
def destroy_button():
for key, value in dict_check_and_buttons:
if value != '' and current_var != '':
key.destroy()
current_box.destroy()
my_friends = ['Donald', 'Daisy', 'Uncle Scrooge']
button1= tk.Button(root, text = "delete both if cbox is checked", command = destroy_button).pack()
#-----ild checkbuttons and store results in checkbutton_result list
checkbutton_result = []
for index, friend in enumerate(my_friends):
current_var = tk.StringVar()
current_box = tk.Checkbutton(root, text= friend,
variable = current_var,
onvalue = friend, offvalue = ""
)
checkbutton_result.append(current_var) #append on and off results
current_box.pack()
#-----build buttons and store them in buttons_list
buttons_list = []
for index, friend in enumerate(my_friends):
buttons= tk.Button(root, text = friend).pack()
buttons_list.append(buttons)
#-----build a dict with list to say "if onvalue != '' destroy button"
dict_check_and_buttons = dict(zip(buttons_list, checkbutton_result))
root.mainloop()
the error is:
Exception in Tkinter callback
Traceback (most recent call last):
File "c:\python\python38\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "<ipython-input-18-954d3a090f2c>", line 7, in destroy_button
for key, value in dict_check_and_buttons:
TypeError: cannot unpack non-iterable NoneType object
There are following issues in your code:
all items in buttons_list are None due to the following line:
buttons= tk.Button(root, text = friend).pack() # buttons is the result of pack()
The line should be split into two lines:
buttons = tk.Button(root, text=friend)
buttons.pack()
you cannot get a (key, value) pair by iterating a dictionary:
for key, value in dict_check_and_buttons: # dict_check_and_buttons is a dictionary
...
Instead you should iterate on the result of dict_check_and_buttons.items():
for key, value in dict_check_and_buttons.items():
...
you need to call get() on a tk.StringVar():
for key, value in dict_check_and_buttons.items():
if value.get() != '': # use value.get()
key.destroy()
If you need to destroy the checkbutton as well, you need to save the checkbutton to checkbutton_result along with its associated variable:
checkbutton_result = []
for index, friend in enumerate(my_friends):
current_var = tk.StringVar()
current_box = tk.Checkbutton(root, text= friend,
variable = current_var,
onvalue = friend, offvalue = ""
)
checkbutton_result.append((current_box, current_var)) # save both checkbutton and its associated variable
current_box.pack()
Then destroy the checkbutton inside destroy_button():
def destroy_button():
for btn, (cb, cbvar) in dict_check_and_buttons.items():
if cbvar.get() != '':
btn.destroy()
cb.destroy()
With your answer I rebuild the code. It is perfect now thanks to you.
import tkinter as tk
root = tk.Tk()
root.geometry('400x400')
'''
to get if checkbox is checked to use results to delete checkbox and label
'''
def destroy_button_box():
for button_names, (ckbox, on_off) in dict_buttons_box_var.items():
if on_off.get() != 0:
button_names.destroy()
ckbox.destroy()
my_friends = ['Donald', 'Daisy', 'Uncle Scrooge']
button1 = tk.Button(root, text="delete label if box is checked", command=destroy_button_box).pack()
checkbox_variable_list = []
box_list = []
for index, friend in enumerate(my_friends):
# current_var = tk.IntVar()
current_var = tk.IntVar()
# current_var = tk.StringVar()
current_box = tk.Checkbutton(root, text=friend,
variable=current_var,
onvalue=1, offvalue=0
)
current_box.pack()
# append checkbox and 'on' or 'off' results
checkbox_variable_list.append((current_box, current_var))
# -----build buttons and store them in buttons_list
buttons_list = []
for index, friend in enumerate(my_friends):
button_names = tk.Button(root, text=friend)
button_names.pack()
# append buttons in loop
buttons_list.append(button_names)
# -----build a dict with lists to use in destroy_box_button function:
dict_buttons_box_var = dict(zip(buttons_list, checkbox_variable_list))
root.mainloop()
Is there a way to restore the same previous session attributes in tkinter ? for example: having one button to restore the previous session attributes
Is there a way to set inputtxt to the value?
def restore():
file1 = open('user.txt', 'r')
Lines = file1.readlines()
unverified_file = Lines[0]
**inputtxt1.set(unverified_file)**
AttributeError: 'Text' object has no attribute 'set'
Looking at your updated code, you need insert not set. But first delete the entry -
def restore():
file1 = open('user.txt', 'r')
Lines = file1.readlines()
unverified_file = Lines[0]
inputtxt1.delete(0,'end')
inputtxt1.insert('end',unverified_file)
Also, take a look at this example -
import tkinter as tk
root = tk.Tk()
def save():
a = entry1.get()
b = entry2.get()
with open('1.txt','w') as f:
f.write(a)
f.write('\n')
f.write(b)
def restore():
with open('1.txt','r') as f:
text = f.read().split('\n')
entry1.insert('end',text[0])
entry2.insert('end',text[1])
entry1 = tk.Entry(root)
entry1.pack()
entry2 = tk.Entry(root)
entry2.pack()
button1 = tk.Button(root,text='Save Results',command=save)
button1.pack()
button2 = tk.Button(root,text='Restore Previous Results',command=restore)
button2.pack()
root.mainloop()
I'm trying to see what checkbox are checked and write a if/else function to do stuff. The number of check boxes depends on the number of topics I parse into the program and create a checkbox for each item.
I added:
chk_state = IntVar()
But this is only good if you are using one checkbox.
I am using a list to generate all my checkboxes:
Which generates these variables for each checkbox:
'chk0', 'chk1', 'chk2', 'chk3', 'chk4', 'chk5', 'chk6', 'chk7', 'chk8', 'chk9', 'chk10', 'chk11', 'chk12', 'chk13', 'chk14', 'chk15', 'chk16', 'chk17', 'chk18', 'chk19', 'chk20', 'chk21', 'chk22', 'chk23', 'chk24']
from tkinter import *
from tkinter import messagebox
from reader import openit
import sys
data = openit(sys.argv[1])
window = Tk()
#set size of window
window.geometry('850x400')
window.title("Chose Your ROS Topic" )
lbl = Label(window, text="Topics", font=("Arial Bold", 25))
lbl.grid(column=0,row=0)
#check checkbox value boolean
chk_state = IntVar()
#chk_state.set(0) #uncheck
#chk_state.set(1) #checked
#Looping through list and adding each one as a checked button
counter = 0
selected_list = []
for x in data.split(","):
# global selected_list
#print(x)
#print(counter)
name = "chk" + str(counter)
# appends each checkbox name to a list
selected_list.append(name)
name = Checkbutton(window, text='%s' % x , font=(15), onvalue=1, offvalue=0, variable=chk_state)
if counter == 0:
name.grid(column=1, row=1)
#print('only for counter 0')
else:
name.grid(column=1, row=1+counter -1)
#print("the rest")
counter += 1
#After selecting all the topics you want to graph
def topics_selected():
#messagebox.showinfo('Topics picked', 'graphing all your checked topics')
#for topics in
if chk_state.get():
print("some checked topics")
else:
print("Nothing is checked")
# Adding input tkinter textbox
txt = Entry(window,width=10)
txt.grid(column=1,row=0)
# Function that changes buttond
def inputcheck():
res = "Topics picked " + txt.get()
lbl.configure(text = res)
def clicked():
lbl.configure(text="Parser was clicked, checking rosbag")
# Adding button widget
btn = Button(window, text="ROS topic parser", bg="orange", fg="black", command=topics_selected)
btn.grid(column=2, row=1)
#Create a checkbox
#chk = Checkbutton(window, text='Choose')
#chk.grid(column=0, row=4)
window.mainloop()
if __name__ == "__main__":
pass
#print(data)
I want to be able to add whatever was selected to a list and push that list to another function.
You need to create a tkinter variable for each Checkbutton. Right now all you Checkbutton shares the same variable chk_state.
To make this work, simply move your definition of IntVar inside the for loop:
...
selected_list = {} #use a dict to store name/IntVar pair; can use a list also
for num, x in enumerate(data.split(",")): #use enumerate to get a num count
chk_state = IntVar() #create a new IntVar in each iteration
selected_list[num] = chk_state #save name/IntVar pair
name = Checkbutton(window, text='%s' % x , font=(15), onvalue=1, offvalue=0, variable=chk_state)
if num == 0:
name.grid(column=1, row=1)
else:
name.grid(column=1, row=1+num-1)
#After selecting all the topics you want to graph
def topics_selected():
if any(s.get() for s in selected_list.values()): #check if any checkbutton is checked
print ("some checked topics")
print ([s.get() for s in selected_list.values()])
else:
print("Nothing is checked")
You could use tk.BooleanVar for each of your check boxes, and set their values inside a for loop.
Keeping the variables in a list allows you to pass the selection to a function.
import tkinter as tk
DEFAULTS = [True, False, False, False]
def display_selected_options(options, values):
for option, value in zip(options, values):
print(f'{option}: {value.get()}')
def create_option_selectors(frame, options, option_variables) -> None:
for idx, option in enumerate(options):
option_variables[idx].set(DEFAULTS[idx])
tk.Checkbutton(frame,
variable=option_variables[idx],
onvalue=True,
offvalue=False,
text=option,
).pack(side=tk.LEFT)
root = tk.Tk()
options = ['chk0', 'chk1', 'chk2', 'chk3']
option_variables = [tk.BooleanVar(root) for _ in range(len(options))]
frame = tk.Frame(root)
create_option_selectors(frame, options, option_variables)
frame.pack()
display_options = tk.Button(root, text='validate', command=lambda options=options,
values=option_variables: display_selected_options(options, values))
display_options.pack()
root.mainloop()
Alternatively, you could use a dictionary to store the option -> value pairs:
Am trying to append the value of radiobutton selected before printing the content in the entry field but am able to append the content in the entry widget to csv file. I would appreciate any help on how to go around achieve that.
from tkinter import *
import csv
with open ("profile.csv", "w") as db:
writer = csv.writer(db)
writer.writerow(["NAME ", "GENDER"]) # create with heading
def save_details():
global e1 # global variable to receive the data from entry
data = e1.get()
#Sex = R1.get
# Sex = R2.get()
totalinput = [ data] # Sex here to append to the csv file
with open("profile.csv", "a") as savedb:
w = csv.writer(savedb)
w.writerow(totalinput)
def validate():
value = option.get() # this for radiobutton
now = new.get() # this for an entry widget
if value != "male" and value != "female":
print("An option must be selected")
else:
print(now)
root = Tk()
root.geometry("400x400")
new = StringVar()
e1 = Entry(root, textvariable=new)
option = StringVar()
R1 = Radiobutton(root, text="MALE", value="male", var=option,
command=save_details, indicatoron=0)
R2 = Radiobutton(root, text="FEMALE", value="female", var=option,
command=save_details, indicatoron=0)
button = Button(root, text="OK", command=validate)
e1.pack()
R1.pack()
R2.pack()
button.pack(side="bottom")
root.mainloop()
Replace:
data = e1.get()
with:
data = option.get()
Radiobuttons share a variable that based on Radiobuttons' state that variable updates its value.
In your case option's value is "male" if R1 is selected and "female" if R2 is selected, as in option.get() returns "male" or "female".
For completeness bind your save_details() and validate function to the OK button.Then add you value to the totalinput list totalinput = [ data, Sex] to append both to the file.
from tkinter import *
import csv
with open ("profile.csv", "w") as db:
writer = csv.writer(db)
writer.writerow(["NAME ", "GENDER"]) # create with heading
def save_details():
global e1 # global variable to receive the data from entry
data = e1.get()
Sex = option.get() # this will get the value of radio selected and append it to the file
totalinput = [ data, Sex] # Sex here to append to the csv file
with open("profile.csv", "a") as savedb:
w = csv.writer(savedb)
w.writerow(totalinput)
def validate():
value = option.get() # this for radiobutton
now = new.get() # this for an entry widget
if value != "male" and value != "female":
print("An option must be selected")
else:
print(now)
root = Tk()
root.geometry("400x400")
new = StringVar()
e1 = Entry(root, textvariable=new)
option = StringVar()
R1 = Radiobutton(root, text="MALE", value="male", var=option, indicatoron=0)
R2 = Radiobutton(root, text="FEMALE", value="female", var=option, indicatoron=0)
button = Button(root, text="OK", command=lambda :[save_details(), validate()])
e1.pack()
R1.pack()
R2.pack()
button.pack(side="bottom")
root.mainloop()
In tkinter, python, I'm creating an info like text editor that uses StringVar() to display a file, also, with the use of entry and a button, I created a delete button, which deletes a certain line in a file. The problem I have is that the file does not delete the specified line and it does not update to show the file's contents. Here's my code:
from tkinter import *
root = Tk()
root.title("text")
root.geometry("700x700")
file = open(r"info.txt", "r")
lines = file.readlines()
file.close()
strd = StringVar()
def updatestr():
fileread = open(r"info.txt", "r")
lines2 = fileread.readlines()
strd.set("{}".format(lines2))
root.after(1, updatestr)
fileread.close()
updatestr()
lads = Label(root, textvariable=strd)
lads.pack()
blank = Label(root, text="")
blank.pack()
blank = Label(root, text="")
blank.pack()
blank = Label(root, text="")
blank.pack()
entry = Entry(root)
entry.configure(width=9)
entry.pack()
def DeleteEntry():
global file
file = open(r"info.txt", "w")
global lines
for line in lines:
if line!="{}".format(entry.get())+"\n":
file.write(line)
file.close()
confent = Button(root, text="Delete", command=DeleteEntry)
confent.configure(width=7)
confent.pack()
Not sure why this is happening, so I'd appreciate some help :)
Thanks