tkinter get values from dynamic checkboxes - python

I am trying to create a number of dynamic checkboxes from data in a XML file.
I have no problems creating the button themselves, but I cant get the values generated by them.
Here is what I got so far...
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
import xml.etree.ElementTree as ET
root = Tk()
def Readstatus():
print(var.get())
listTree = ET.parse('list.xml')
listRoot = listTree.getroot()
var = dict()
count=1
for child in listRoot:
var[child]=IntVar()
chk = Checkbutton(root, text='Text'+str(count), variable=var[child], command=Readstatus)
count += 1
chk.pack()
root.mainloop()
Any help would be greatly apreciated!
Gilles

The event handler will return a TypeError as it expects 1 argument and got nothing. To make this a bit simpler, I modified the code so that it the key to the event handler.
from tkinter import *
from tkinter import ttk
import xml.etree.ElementTree as ET
root = Tk()
def Readstatus(key):
print(var.get(key))
listTree = ET.parse('test.xml')
listRoot = listTree.getroot()
var = dict()
count=1
for child in listRoot:
var[child]=IntVar()
chk = Checkbutton(root, text='Text'+str(count), variable=var[child],
command=lambda key=child: Readstatus(key))
count += 1
chk.pack()
root.mainloop()
This worked for me. I do think using Element objects for keys in the dictionary is a bit hard to debug, but I'm sure you have a good reason for doing that.
EDIT
To get just a 1 or 0 returned, change the event handler to look like this:
def Readstatus(key):
var_obj = var.get(key)
print(var_obj.get())
The var.get() command is actually calling a dictionary object's get() method, which is why it requires a key passed to it. Once you have the IntVar object returned, you can call its own get method to return the 0 or 1. See also:
http://effbot.org/tkinterbook/checkbutton.htm

Related

Retrieving values from dynamic checkbuttons

I am using a for loop to create checkbuttons based off a list. I then want a button that'll "get" which buttons have been checked or not.
Since I am not manually creating the checkbuttons, I am not naming the variables so how can I .get() whether they are on or off?
Thanks very much this worked nicely
'''
from tkinter import *
root = Tk()
shopping = ['Apples','Pears','Bananas']
chbuttonlist = []
for item in shopping:
var = StringVar()
b = Checkbutton(root,text=item,variable=var)
b.deselect()
b.pack()
chbuttonlist.append(var)
def printlist():
lst=[]
for var in chbuttonlist:
lst.append(var.get())
for i in range(len(lst)):
if lst[i]=='1':
print(shopping[i])
Button(root,text='Click to print checked items',command=printlist).pack()
root.mainloop()
'''

Retrieving value from Tkinter combobox

Eventually I want to use the values in the comboboxes as parameters in other functions, but I think if I can just get them to print for now, that will be enough to build off of. Here's what I have so far.
import tkinter as tk
from tkinter import ttk
import time
def ok():
betType = betTypeVar.get()
season = seasonVar.get()
print(betType, season)
def CreateSimPreviousSeasonWindow():
prevSeasonWindow = tk.Tk()
#============= Bet Type Input =============#
betTypeVar = tk.StringVar()
betTypeLabel = tk.Label(prevSeasonWindow, text="Bet type:").grid(row=0,column=0)
betTypeChosen = ttk.Combobox(prevSeasonWindow, values=['Moneyline','Total'])
betTypeChosen.grid(row=0, column=1)
seasonVar = tk.StringVar()
seasonLabel = tk.Label(prevSeasonWindow, text='Season:').grid(row=1, column=0)
seasonChosen = ttk.Combobox(prevSeasonWindow, values=['2018', '2017'])
seasonChosen.grid(row=1,column=1)
button = tk.Button(prevSeasonWindow, text='OK', command=ok)
button.grid(row=2,column=0)
prevSeasonWindow.mainloop()
This gives me
File "C:[directory...]", line 6, in ok
betType = betTypeVar.get()
NameError: name 'betTypeVar' is not defined
To me it looks pretty obvious that this error is because ok() doesn't have any parameters passed to it, so it has no idea what 'betTypeVar' is, but all the tutorials I've read do it this way, so I'm missing something. If I try actually passing ok() the arguments, it still doesn't work.
There are two things to fix in your code. First let's focus on CreateSimPreviousSeasonWindow:
betTypeVar = tk.StringVar()
seasonVar = tk.StringVar()
You defined two StringVar but you actually never used it or linked them to your combobox object. The correct way is to set them as a textvaraible:
betTypeChosen = ttk.Combobox(prevSeasonWindow, textvariable=betTypeVar, values=['Moneyline','Total'])
seasonChosen = ttk.Combobox(prevSeasonWindow, textvariable=seasonVar, values=['2018', '2017'])
Next, NameError: name 'betTypeVar' is not defined is due to your variables being local variables. You are trying to access the same variable across different functions. To pass them around, you need to declare global:
def ok():
global betTypeVar, seasonVar
betType = betTypeVar.get()
season = seasonVar.get()
print(betType, season)
def CreateSimPreviousSeasonWindow():
global betTypeVar, seasonVar
...
Also I want to point out that if you just want to retrieve the values of the combobox, you don't really need to create two StringVar. Just combobox.get() already works good enough.
import tkinter as tk
from tkinter import ttk
import time
def ok():
global betTypeChosen, seasonChosen
print (betTypeChosen.get(), seasonChosen.get())
def CreateSimPreviousSeasonWindow():
global betTypeChosen,seasonChosen
prevSeasonWindow = tk.Tk()
#============= Bet Type Input =============#
betTypeLabel = tk.Label(prevSeasonWindow, text="Bet type:").grid(row=0,column=0)
betTypeChosen = ttk.Combobox(prevSeasonWindow,values=['Moneyline','Total'])
betTypeChosen.grid(row=0, column=1)
seasonLabel = tk.Label(prevSeasonWindow, text='Season:').grid(row=1, column=0)
seasonChosen = ttk.Combobox(prevSeasonWindow, values=['2018', '2017'])
seasonChosen.grid(row=1,column=1)
button = tk.Button(prevSeasonWindow, text='OK', command=ok)
button.grid(row=2,column=0)
prevSeasonWindow.mainloop()
CreateSimPreviousSeasonWindow()

Need to track variables from multiple Tkinter checkboxes

I have a dynamically created Tkinter checkbutton widget, which takes in the contents of a list of usernames. I then displayed those names with a checkbox alongside.
What I need to do is obviously collect which usernames have been checked, so I can pass that off to another function to action.
How should I write the variable part of this so it creates a new list of chosen usernames?
What I have thus far:
def delprof_results(users_delprof):
for i in range(len(users_delprof)):
c = Checkbutton(resultsFrame, text=users_delprof[i], variable=users_delprof[i])
c.pack(anchor=W)
def delprof_del():
users_chosen = []
print str(users_delprof[i]).get() # Works up until this point. How to get individual variable with ID.
del_but = Button(resultsFrame, text="Delete", width=7, height=1, command=delprof_del)
del_but.pack(side=LEFT)
Thanks in advance,
Chris.
If you want to reach individual objects, simply keep a reference to the individual objects instead of creating objects while overwriting the same variable with each iteration of a loop like:
for i in range(30):
a = i
How to reach a's state where it was 13? Well, you can't as it's overwritten.
Instead, use collection types. In the example below I used dict:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except ImportError:
import Tkinter as tk
def upon_select(widget):
print("{}'s value is {}.".format(widget['text'], widget.var.get()))
if __name__ == '__main__':
root = tk.Tk()
names = {"Chester", "James", "Mike"}
username_cbs = dict()
for name in names:
username_cbs[name] = tk.Checkbutton(root, text=name,
onvalue=True, offvalue=False)
username_cbs[name].var = tk.BooleanVar()
username_cbs[name]['variable'] = username_cbs[name].var
username_cbs[name]['command'] = lambda w=username_cbs[name]: \
upon_select(w)
username_cbs[name].pack()
tk.mainloop()
You could make a list of values from the checkbuttons:
values = []
for i in range(len(users_delprof)):
v = IntVar()
c = Checkbutton(master, text="Don't show this again", variable=v)
c.var = v
values.append(v)
Now you can check the value by looking in the list values, and getting the value of a checkbutton with v.get().

Returning PY_VARxxx instead of expected string

I'm currently creating a GUI in order to turn a lot of individual instruments into one complete system. In def smuSelect(self) I create a list self.smuChoices I can use to call individual choices such as smuChoices[0] and it will return "2410(1)".
Once I call def checkBoxSetup it returns PY_VARxxx. I've tried searching the different forums and everything. I've seen mentions using the .get() which just gives me the state of the individual choice. The reason I want the actual string itself is I would like to use it in def testSetup(self) for the user to assign specific names to the individual machine, for example, 2410 = Gate.
My initial attempt was to create another variable smuChoice2 but I believe this is still changing the original list self.smuChoices.
import tkinter as tk
import numpy as np
from tkinter import ttk
def checkBoxSetup(smuChoice2): #TK.INTVAR() IS CHANGING NAME OF SMUS NEED TO CREATE ANOTHER INSTANCE OF SELF.SMUCHOICES
for val, SMU in enumerate(smuChoice2):
smuChoice2[val] = tk.IntVar()
b = tk.Checkbutton(smuSelection,text=SMU,variable=smuChoice2[val])
b.grid()
root = tk.Tk()
root.title("SMU Selection")
"""
Selects the specific SMUs that are going to be used, only allow amount up to chosen terminals.
--> If only allow 590 if CV is picked, also only allow use of low voltage SMU (maybe dim options that aren't available)
--> Clear Checkboxes once complete
--> change checkbox selection method
"""
smuChoices = [
"2410(1)",
"2410(2)",
"6430",
"590 (CV)",
"2400",
"2420"
]
smuChoice2 = smuChoices
smuSelection = ttk.Frame(root)
selectInstruct = tk.Label(smuSelection,text="Choose SMUs").grid()
print(smuChoices[0]) #Accessing list prior to checkboxsetup resulting in 2410(1)
checkBoxSetup(smuChoice2)
print(smuChoices[0]) #Accessing list after check box setup resulting in PY_VAR376
variableSMUs = tk.StringVar()
w7_Button = tk.Button(smuSelection,text="Enter").grid()
w8_Button = tk.Button(smuSelection,text="Setup Window").grid()
root.mainloop()
I was able to solve the problem by changing my list, smuChoices, to a dictionary then modifying
def checkBoxSetup(smuChoice2):
for val, SMU in enumerate(smuChoice2):
smuChoice2[val] = tk.IntVar()
b = tk.Checkbutton(smuSelection,text=SMU,variable=smuChoice2[val])
b.grid()
to
def checkBoxSetup(self):
for i in self.smuChoices:
self.smuChoices[i] = tk.IntVar()
b = tk.Checkbutton(self.smuSelection,text=i,variable=self.smuChoices[i])
b.grid()
Previously I was replacing the variable with what I'm guessing is some identifier that tkinter uses to store the state which is why I was getting PYxxx.
First of all getting PY_VARXX instead of what's in a variable class indicates the lack of get().
replace:
print(self.smuChoices[0])
with:
print(self.smuChoices[0].get())
Secondly, if you want to display the value of a variable class on a label, button, etc. you could rather just use the textvariable option by simply assigning the variable class to it.
Replace:
tk.Label(self.smuName,text=SMU).grid()
with:
tk.Label(self.smuName, textvariable=self.smuChoices[val]).grid()
Your question is still a bit unclear to me but I will try to provide an answer to the best of my understanding.
As I understand it, you're trying to create a set of Checkbuttons for a given list of items. Below is an example of a method that takes items as an argument and returns a dictionary of checkboxes that have root as their parent:
import tkinter as tk
def dict_of_cbs(iterable, parent):
if iterable:
dict_of_cbs = dict()
for item in iterable:
dict_of_cbs[item] = tk.Checkbutton(parent)
dict_of_cbs[item]['text'] = item
dict_of_cbs[item].pack() # it's probably a better idea to manage
# geometry in the same place wherever
# the parent is customizing its
# children's layout
return dict_of_cbs
if __name__ == '__main__':
root = tk.Tk()
items = ("These", "are", "some", "items.")
my_checkboxes = dict_of_cbs(items, root)
root.mainloop()
Additionally note that I haven't used any variable classes (BooleanVar, DoubleVar, IntVar or StringVar) as they seem to be redundant in this particular case.

How to get content of ScrolledText?

I'm trying to get content of a ScrolledText but so far success is not with me :)
I don't understand where i'm wrong.
Here a very simple example of not working code...
from Tkinter import Tk
from ScrolledText import ScrolledText
def returnPressed(value):
print "CONTENT: " + value
root = Tk()
st = ScrolledText(root)
st.bind("<Return>", lambda event, i=st.get("1.0", "end-1c"): returnPressed(i))
st.insert("insert", "TEST")
st.pack()
root.mainloop()
Ok this is because of lambda definition.
By this way, function is created with constant "i" value, which is the value at declaration of function.
By rewording lambda as it, it works!
st.bind("<Return>", lambda event: returnPressed(st.get("1.0", "end-1c")))
You are getting the value at the time you create the button, which means the value will always be empty. You need to get the value at the time that the event is processed.
You should avoid using lambda, it is a somewhat advanced concept that in this case adds complexity without adding any value. Simply get the value from within the function:
def returnPressed(event):
value = event.widget.get("1.0", "end-1c")
print "CONTENT: " + value
...
st.bind("<Return>", returnPressed)

Categories