Skip to content Skip to sidebar Skip to footer

How Do I Simulate A Scrollbar In Tkinter Canvas

I'm creating a game launcher specially in Python 3.7 tkInter, and I want to make my own styled Scrollbar (in Windows 10 (version 1903)). I've tried adding a hidden Scrollbar, and h

Solution 1:

How do i simulate a Scrollbar in Tkinter Canvas

The scrollbar has a well defined interface. To simulate a scrollbar all you need to do is implement this interface. This is most easily done by creating a class that has the following attributes:

  • you need to define the set method, which is called whenever the widget being scrolled wants to update the scrollbar
  • you need to add mouse bindings to call the yview method of the widget being controlled by the scrollbar (or xview if creating a horizontal widget).

If you do those two things, your scrollbar can be used exactly like a built-in scrollbar.

For the rest of this answer, I'm going to assume you want to simulate a vertical scrollbar. Simulating a horizontal scrollbar works identically, but instead of 'top' and 'bottom', you are dealing with 'left' and right'.

Defining the set method

The set method will be called with two fractions. The canonical documentation describes it like this:

This command is invoked by the scrollbar's associated widget to tell the scrollbar about the current view in the widget. The command takes two arguments, each of which is a real fraction between 0 and 1. The fractions describe the range of the document that is visible in the associated widget. For example, if first is 0.2 and last is 0.4, it means that the first part of the document visible in the window is 20% of the way through the document, and the last visible part is 40% of the way through.

Defining the bindings

The other half of the equation is when the user interacts with the scrollbar to scroll another widget. The way this happens is that the scrollbar should call the yview command of the widget to be controlled (eg: canvas, text, listbox, etc).

The first argument you must pass to the command is either the string "moveto" or "scroll".

  • If "moveto", the second argument is a fraction which represents the amount that has been scrolled off of the top. This is typically called when clicking on the scrollbar, to immediately move the scrollbar to a new position

  • if "scroll", the second argument is an integer representing an amount, and the third argument is either the string "units" or "pages". The definition of "units" refers to the value of the yscrollincrement option. "pages" represents 9/10ths of the window height. This is typically called when dragging the mouse over the scrollbar.

The options are spelled out in the man pages for each scrollable widget.

Example

The following is an example of a uses a text widget, so that you can see that when you type, the scrollbar properly grows and shrinks. If you click anywhere in the scrollbar, it will scroll to that point in the documentation.

To keep the example short, this code doesn't handle dragging the scrollbar, and it hard-codes a lot of values that probably ought to be configurable. The point is to show that all you need to do to simulate a scrollbar is create a class that has a set method and which calls the yview or xview method of the connected widget.

First, the scrollbar class

import tkinter as tk

classCustomScrollbar(tk.Canvas):
    def__init__(self, parent, **kwargs):
        self.command = kwargs.pop("command", None)
        tk.Canvas.__init__(self, parent, **kwargs)

        # coordinates are irrelevant; they will be recomputed# in the 'set' method
        self.create_rectangle(0,0,1,1, fill="red", tags=("thumb",))
        self.bind("<ButtonPress-1>", self.on_click)

    defset(self, first, last):
        first = float(first)
        last = float(last)
        height = self.winfo_height()
        x0 = 2
        x1 = self.winfo_width()-2
        y0 = max(int(height * first), 0)
        y1 = min(int(height * last), height)
        self.coords("thumb", x0, y0, x1, y1)

    defon_click(self, event):
        y = event.y / self.winfo_height()
        self.command("moveto", y)

Using the class in a program

You would use this class exactly like you would a native scrollbar: instantiate it, and set the command to be the yview command of a scrollable widget.

This example uses a text widget so you can see the scrollbar updating as you type, but the exact same code would work with a Canvas, or any other scrollable window.

root = tk.Tk()

text = tk.Text(root)
sb = CustomScrollbar(root, width=20, command=text.yview)
text.configure(yscrollcommand=sb.set)

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

with open(__file__, "r") as f:
    text.insert("end", f.read())

root.mainloop()

Post a Comment for "How Do I Simulate A Scrollbar In Tkinter Canvas"