Search code examples
pythontkinterscrollbarinfinite-scroll

Tkinter | How to detect tkinter scrollbar position near the end


I know that you can get the scrollbar position if I bind the frame the scrollbar is controlling to a function (onFrameConfigure) like this: self.calendar_frame.bind("<Configure>", self.onFrameConfigure), and from the event in the onFrameConfigure(self, event): I can get some x value of the scroll bar event.x. I thought the value was showing the location of the scrollbar in px so with that logic if I scroll to the maximum right side, I should get the same value (or similar value) as the width of the scrollbar but from the test below I got otherwise:

event.x: -640 | scrollbar.winfo_width(): 382
event.x: -415 | scrollbar.winfo_width(): 607
event.x: -245 | scrollbar.winfo_width(): 777
event.x: -713 | scrollbar.winfo_width(): 309

(the result above are only when the scrollbar is to the maximum right)

Don't see any way to use those value to determine whether the scrollbar is at the right end.

My question is: how can I detect when the scrollbar reached the end of one of the end-of-the-scrollbar?

Even better would be to detect when the scrollbar is near the end because for my purpose (read the purpose of my project here: here) I need something to trigger right before the scrollbar reach it maximum end.


Solution

  • If you're wanting to know when the scrolled widget is scrolled toward the edge, the simplest solution is to call a custom command rather than calling the set method of the associated scrollbar. This command can itself call the set method, and then do whatever else you want it to do.

    This command will be passed two parameters which represent the range of the viewport into the scrolled widget. The numbers are floating point numbers between 0 and 1, though they are passed as strings rather than floats. The first number represents the first visible part of the widget, and the second number represents the last part of the visible widget.

    For example, normally you would do something like this to wire a canvas and scrollbar together:

    canvas = tk.Canvas(...)
    scrollbar = tk.Scrollbar(..., command=canvas.xview)
    canvas.configure(xscrollcommand=scrollbar.set)
    

    Instead, create your own command which calls the scrollbar.set method and then does whatever else you want it to do. It would look something like this:

    def handle_scroll(x0, x1):
        hsb.set(x0, x1)
        if float(x1) > .9:
            ...
    
    canvas = tk.Canvas(...)
    scrollbar = tk.Scrollbar(..., command=canvas.xview)
    canvas.configure(xscrollcommand=handle_scroll)