问题
Checkbuttons gets generated dynamically and they are getting text from a python list. I need a logic for capturing selected checkbuttons text . As per my research everywhere they are returning the state of checkbox instead of text. Please help.
cb_list =['pencil','pen','book','bag','watch','glasses','passport','clothes','shoes','cap']
try:
r = 0
cl = 1
for op in cb_list:
cb = Checkbutton(checkbutton_frame, text=op, relief=RIDGE)
cb.grid(row=r, column=cl, sticky="W")
r = r + 1
except Exception as e:
logging.basicConfig(filename=LOG_FILENAME, level=logging.ERROR)
logging.error(e)
# print (e)
selected_item = Text(self, width=30, height=20, wrap=WORD)
selected_item.grid(row=1, column=6, padx=20, pady=20, columnspan=2, sticky=E)
display_button = Button(self, text='DISPLAY', command=display()
convert_button.grid(row=1, column=8, padx=20, pady=20)
回答1:
Instead of overwriting the same variable, cb
, try using an iterable type such as dict
ionary. You should also need to be attaching the value of Checkbutton
to a tkinter variable class, such as BooleanVar
, in order to easily track its status & value.
The code below produces a GUI that re-writes Text
each time a Checkbutton
is selected. It first populates a dictionary, cbs
, with items from a list, cb_list
, as keys and tk.Checkbutton
objects as the values.
Checkbutton
objects are so that each is attached to a special object, Tkinter Variable class, BooleanVar
, which has a get
method that returns the Checkbutton
it is attached to's current value when called. In this case, each Checkbutton
holds True
if checked, and False
if unchecked as its value.
Each Checkbutton
is also attached to a method, update_text
, which is called when any of the Checkbutton
is pressed. In that method for every Checkbutton
in cbs
, it first checks if the Checkbutton
has True
value, if so it appends its text
to a _string
. After this has been done for all Checkbuttons
, the method then proceeds as first delete
ing the entire text in the Text
widget, then it puts _string
to the Text
.
The code:
import tkinter as tk
def update_text():
global cbs
_string = ''
for name, checkbutton in cbs.items():
if checkbutton.var.get():
_string += checkbutton['text'] + '\n'
text.delete('1.0', 'end')
text.insert('1.0', _string)
if __name__ == '__main__':
root = tk.Tk()
text = tk.Text(root)
cb_list =['pencil','pen','book','bag','watch','glasses','passport',
'clothes','shoes','cap']
cbs = dict()
for i, value in enumerate(cb_list):
cbs[value] = tk.Checkbutton(root, text=value, onvalue=True,
offvalue=False, command=update_text)
cbs[value].var = tk.BooleanVar(root, value=False)
cbs[value]['variable'] = cbs[value].var
cbs[value].grid(row=i, column=0)
text.grid()
root.mainloop()
text
is an option to Checkbutton
widget, which means you can get its value using cget(widget.cget('option')
) or simply widget['option']
.
回答2:
The idea is to associate one BooleanVar
to each checkbutton and store them in a list cb_var
. Then, to display the selected items, we just have to clear the display box (I have used a Listbox
) and then loop simultaneously through cb_list
and cb_var
to determine which items are selected:
import tkinter as tk
root = tk.Tk()
checkbutton_frame = tk.Frame(root)
checkbutton_frame.grid(row=1, column=0)
def display():
# clear listbox
selected_item.delete(0, 'end')
# add selected items in listbox
for text, var in zip(cb_list, cb_var):
if var.get():
# the checkbutton is selected
selected_item.insert('end', text)
cb_list = ['pencil','pen','book','bag','watch','glasses','passport','clothes','shoes','cap']
cb_var = [] # to store the variables associated to the checkbuttons
cl = 1
for r, op in enumerate(cb_list):
var = tk.BooleanVar(root, False)
cb = tk.Checkbutton(checkbutton_frame, variable=var, text=op, relief='ridge')
cb.grid(row=r, column=cl, sticky="w")
cb_var.append(var)
selected_item = tk.Listbox(root, width=30, height=20)
selected_item.grid(row=1, column=6, padx=20, pady=20, columnspan=2, sticky='e')
display_button = tk.Button(root, text='DISPLAY', command=display)
display_button.grid(row=1, column=8, padx=20, pady=20)
root.mainloop()
EDIT: If you want to be able to change the list of items easily, you can use a function init_checkbuttons
to create the checkbuttons from your list
of items. This function does the following things:
- Destroy all previous checkbuttons
- Clear the listbox
- Create the new checkbuttons
- Change the command of the display button
You can notice that the display
function now takes cb_list
and cb_var
in argument, so that you can change them.
import tkinter as tk
root = tk.Tk()
checkbutton_frame = tk.Frame(root)
checkbutton_frame.grid(row=1, column=0)
def display(cb_list, cb_var):
# clear listbox
selected_item.delete(0, 'end')
# add selected items in listbox
for text, var in zip(cb_list, cb_var):
if var.get():
# the checkbutton is selected
selected_item.insert('end', text)
def init_checkbuttons(cb_list, cl=1):
# destroy previous checkbuttons (assuming that checkbutton_frame only contains the checkbuttons)
cbs = list(checkbutton_frame.children.values())
for cb in cbs:
cb.destroy()
# clear listbox
selected_item.delete(0, 'end')
# create new checkbuttons
cb_var = [] # to store the variables associated to the checkbuttons
for r, op in enumerate(cb_list):
var = tk.BooleanVar(root, False)
cb = tk.Checkbutton(checkbutton_frame, variable=var, text=op, relief='ridge')
cb.grid(row=r, column=cl, sticky="w")
cb_var.append(var)
# change display command
display_button.configure(command=lambda: display(cb_list, cb_var))
cb_list = ['pencil', 'pen', 'book', 'bag', 'watch', 'glasses', 'passport', 'clothes', 'shoes', 'cap']
cb_list2 = ['ball', 'table', 'bat']
selected_item = tk.Listbox(root, width=30, height=20)
selected_item.grid(row=1, column=6, padx=20, pady=20, columnspan=2, sticky='e')
display_button = tk.Button(root, text='DISPLAY')
display_button.grid(row=1, column=8, padx=20, pady=20)
tk.Button(root, text='Change list', command=lambda: init_checkbuttons(cb_list2)).grid(row=2, column=8)
init_checkbuttons(cb_list)
root.mainloop()
来源:https://stackoverflow.com/questions/48436622/how-to-get-the-text-of-checkbuttons