Grendel
Grendel

Reputation: 25

Adding a list of checkbuttons to a scrolled text widget

I need to have checkbuttons inside a scrolled text widget, one checkbutton per row and some text behind each button. I found this solution an stackoverflow:

Tkinter checkbuttons inside of a Text widget and scrolling

Here's a code snipped:

for i in range(1000):
    bg = 'grey'
    if i % 2 == 0:
        bg = 'white'
    cb = tk.Checkbutton(text="checkbutton #%s" % i, bg=bg, width=35, justify=tk.LEFT)
    text.window_create("end", window=cb)
    text.insert("end", "\n") # to force one checkbox per line

This doesn't make much sense to me because while the checkbuttons are displayed correctly you don't have access to each of them. Or am I wrong?

Upvotes: 0

Views: 1445

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385960

Like with any other python object, in order to call methods on it you need to have a reference. The simplest solution is to keep references to the widget and the variable in a list or dictionary.

For example:

import tkinter as tk

class Example(object):
    def __init__(self):

        root = tk.Tk()
        text = tk.Text(root, cursor="arrow")
        vsb = tk.Scrollbar(root, command=text.yview)
        button = tk.Button(root, text="Get Values", command=self.get_values)
        text.configure(yscrollcommand=vsb.set)

        button.pack(side="top")
        vsb.pack(side="right", fill="y")
        text.pack(side="left", fill="both", expand=True)

        self.checkbuttons = []
        self.vars = []
        for i in range(20):
            var = tk.IntVar(value=0)
            cb = tk.Checkbutton(text, text="checkbutton #%s" % i,
                                variable=var, onvalue=1, offvalue=0)
            text.window_create("end", window=cb)
            text.insert("end", "\n")
            self.checkbuttons.append(cb)
            self.vars.append(var)
        text.configure(state="disabled")

        root.mainloop()

    def get_values(self):
        for cb, var in zip(self.checkbuttons, self.vars):
            text = cb.cget("text")
            value = var.get()
            print("%s: %d" % (text, value))

if __name__ == "__main__":
    Example()

Upvotes: 2

Related Questions