-3

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)

2 Answers2

1

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()

enter image description here

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:

  1. Destroy all previous checkbuttons
  2. Clear the listbox
  3. Create the new checkbuttons
  4. 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()
j_4321
  • 15,431
  • 3
  • 34
  • 61
  • how to clear the checkbuttons ? Now the list is this: cb_list = ['pencil','pen','book','bag','watch','glasses','passport','clothes','shoes','cap'] but if the list changes in second iteration cb_list = ['ball','table','bat'] So I want to clear previous check buttons to get new checkbuttons I tried with checkbutton.destroy() but it destroys and would not create new checkbuttons – Priyanka Baviskar Jan 27 '18 at 11:57
0

Instead of overwriting the same variable, cb, try using an iterable type such as dictionary. 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 deleteing 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'].

Nae
  • 14,209
  • 7
  • 52
  • 79