0

I'm using a checkboxtreeview widget from the ttkwidgets module in my Python script. By setting the state to "checked", "unchecked" or "tristate", I can make the checkbox of an item to appear accordingly as expected.

Is there any way to disable the checkbox, i.e. that the user can't change the state anymore by clicking it?

Thanks a lot for any help!

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
petro4213
  • 163
  • 9
  • `.state = ['disabled']` and `.state = ['normal']` – stovfl May 06 '19 at 12:34
  • Thanks, but not quite... As the checkbox itself is not available as a widget (unless you dig deeply into the checkboxtreeview object), I can't set the state like this. However, if I use `self.tree.change_state(item, 'disabled')` I can make the checkbox disappear from the treeview, which is just as good as disabling. Actually any string used in the `change_state` call that is not `"checked"`, `"unchecked"`, or `"tristate"` makes the checkbox disappear. – petro4213 May 07 '19 at 10:58
  • Do you have any reference about `checkboxtreeview widget`? – stovfl May 07 '19 at 19:51
  • I found a reference to this widget, which is part of the ttkwidgets that can be installed using pip, on this thread [link](https://stackoverflow.com/questions/5104330/how-to-create-a-tree-view-with-checkboxes-in-python). Unfortunately, there's not much documentation, but at least the Python doc feature shows a few hints. – petro4213 May 08 '19 at 07:50

1 Answers1

4

You can add a "disabled" tag and check in the _box_click() function that is called when the user clicks in the tree that the item is not disabled before changing its state. In the code below I copied the source code of the _box_click() method and added

if self.tag_has("disabled", item):
    return  # do nothing when disabled

to disable the state change. I also configured the "disabled" tag so that the font is lighter to be able to see disabled items: self.tag_configure("disabled", foreground='grey')

Here the full code with an example:

import ttkwidgets as tw
import tkinter as tk

class CheckboxTreeview(tw.CheckboxTreeview):

    def __init__(self, master=None, **kw):
        tw.CheckboxTreeview.__init__(self, master, **kw)
        # disabled tag to mar disabled items
        self.tag_configure("disabled", foreground='grey')

    def _box_click(self, event):
        """Check or uncheck box when clicked."""
        x, y, widget = event.x, event.y, event.widget
        elem = widget.identify("element", x, y)
        if "image" in elem:
            # a box was clicked
            item = self.identify_row(y)
            if self.tag_has("disabled", item):
                return  # do nothing when disabled
            if self.tag_has("unchecked", item) or self.tag_has("tristate", item):
                self._check_ancestor(item)
                self._check_descendant(item)
            elif self.tag_has("checked"):
                self._uncheck_descendant(item)
                self._uncheck_ancestor(item) 

root = tk.Tk()

tree = CheckboxTreeview(root)
tree.pack()

tree.insert("", "end", "1", text="1")
tree.insert("1", "end", "11", text="11", tags=['disabled'])
tree.insert("1", "end", "12",  text="12")
tree.insert("11", "end", "111", text="111")
tree.insert("", "end", "2", text="2")
root.mainloop()
j_4321
  • 15,431
  • 3
  • 34
  • 61