0

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?

Community
  • 1
  • 1
Grendel
  • 25
  • 9
  • What do you mean by "don't have access"? Why don't you have access? In this specific code you keep overwriting your `cb` variable, but there is no reason why you can't add the checkbuttons to a list or dictionary. – Bryan Oakley Apr 06 '17 at 12:21
  • Yes, this is what I meant: you permanently overwrite the variable bound to the checkbuttons. Can you please give me a hint on how to use lists or a dictionary to get the state of each checkbutton? In the above example, does something like cb[i] = tk.Checkbutton ... work? – Grendel Apr 06 '17 at 12:46
  • There's nothing tkinter-specific going on here. You solve this the same way you would solve creating strings or numbers or objects of any other type in a loop. Append them to a list, add them to a dictionary, you can do it however you want. – Bryan Oakley Apr 06 '17 at 13:06
  • Hm, whatever I try, it doesn't work. All checkbuttons, as well as lot's of hyperlinks inside the text widget, are generic, created inside a loop. I'm not able to use any kind of list index to variables which are normally used to access the state of a checkbutton. My standard way of checking whether a checkbutton is selected is by using 'my_variable = IntVar()'. When I try to use this with a list index like this 'my_variable[i] = IntVar()' I get an error message. I've similar problems creating generic hyperlinks. – Grendel Apr 07 '17 at 22:57

1 Answers1

2

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()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685