Home > Net >  Tkinter (Python) checkbox inside scrollbar
Tkinter (Python) checkbox inside scrollbar

Time:01-15

I'm trying to create a scroll full of checkboxes but I'm having 3 problems:

  1. I can't center the scroll sidebar
  2. I can't define a scroll size of my choice
  3. it seems that if the mouse is over the checkboxes the scroll doesn't work and I have to go to an area without checkboxes

This is my code:

    text = tk.Text(self, cursor="arrow")
    vsb = tk.Scrollbar(self, command=text.yview)
    vsb.grid(row=7, column=4, rowspan=2, sticky='nse')
    text.configure(yscrollcommand=vsb.set, width=20)
    text.grid(row=7, column=4, rowspan=2, columnspan=1)
    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")

I'm also open to other solutions but basically I need a scroll with a variable number of checkboxes inside. and I would like the scroll size to be well defined

CodePudding user response:

You can use a 'Frame' widget to hold the checkboxes and scrollbar, and then use the 'grid' geometry manager to place the checkboxes in a grid within the frame. Then you can use the 'scrollbar' and 'canvas' widgets to add scrolling functionality to the frame.

import tkinter as tk

class CheckboxList(tk.Frame):
    def __init__(self, master=None, **kw):
        super().__init__(master, **kw)
        self.checkbuttons = []
        self.vars = []
        self.canvas = tk.Canvas(self, bg='white', bd=0, highlightthickness=0)
        self.yscroll = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.frame = tk.Frame(self.canvas)
        self.canvas.create_window((0, 0), window=self.frame, anchor='nw')
        self.canvas.configure(yscrollcommand=self.yscroll.set)
        self.canvas.grid(row=0,column=0,sticky='nsew')
        self.yscroll.grid(row=0,column=1,sticky='nse')
        for i in range(20):
            var = tk.IntVar(value=0)
            cb = tk.Checkbutton(self.frame, text=f"checkbutton #{i}", variable=var, onvalue=1, offvalue=0)
            cb.grid(row=i, column=0, sticky='w')
            self.checkbuttons.append(cb)
            self.vars.append(var)
        self.frame.update_idletasks()
        self.canvas.config(scrollregion=self.canvas.bbox("all"))

root = tk.Tk()
cl = CheckboxList(root, width=20, height=10)
cl.grid(row=0,column=0,sticky='nsew')
root.mainloop()

This will create a canvas widget and a frame widget, the checkboxes will be added to the frame and the canvas will be scrolled as desired. This should give you the desired effect of a scrollbar with a variable number of checkboxes inside.

EDIT : To enable mouse wheel scrolling, you need to bind the mouse wheel to the canvas widget's 'yview' method.

import tkinter as tk

class CheckboxList(tk.Frame):
    def __init__(self, master=None, **kw):
        super().__init__(master, **kw)
        self.checkbuttons = []
        self.vars = []
        self.canvas = tk.Canvas(self, bg='white', bd=0, highlightthickness=0)
        self.yscroll = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.frame = tk.Frame(self.canvas)
        self.canvas.create_window((0, 0), window=self.frame, anchor='nw')
        self.canvas.configure(yscrollcommand=self.yscroll.set)
        self.canvas.grid(row=0,column=0,sticky='nsew')
        self.yscroll.grid(row=0,column=1,sticky='nse')
        for i in range(20):
            var = tk.IntVar(value=0)
            cb = tk.Checkbutton(self.frame, text=f"checkbutton #{i}", variable=var, onvalue=1, offvalue=0)
            cb.grid(row=i, column=0, sticky='w')
            self.checkbuttons.append(cb)
            self.vars.append(var)
        self.frame.update_idletasks()
        self.canvas.config(scrollregion=self.canvas.bbox("all"))
        
        self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
        
    def _on_mousewheel(self, event):
        self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")

root = tk.Tk()
cl = CheckboxList(root, width=20, height=10)
cl.grid(row=0,column=0,sticky='nsew')
root.mainloop()

This should work.

  • Related