0

Is there any way to scroll one widget with another in tkinter?

Here's the code:

from tkinter import *

root = Tk()

def yview(*args):
    text_widget_1.yview(*args)
    text_widget_2.yview(*args)

scrollbar = Scrollbar(root , orient = VERTICAL , command = yview)
scrollbar.grid(row = 0 , column = 2 , sticky = N+S+E+W)

text_widget_1 = Text(root , width = 3 , height = 25 , yscrollcommand = scrollbar.set , font = "consolas 14")
text_widget_1.grid(row = 0 , column = 0)

text_widget_2 = Text(root , width = 35 , height = 25 , yscrollcommand = scrollbar.set , font = "consolas 14")
text_widget_2.grid(row = 0 , column = 1 , padx = 2)

for i in range(1,500):
    text_widget_1.insert(END , f"{i}\n")
    text_widget_2.insert(END , f"Line no: {i}\n")

mainloop()

Here, when I move the scrollbar, both the text widgets are scrolled, and everything works fine.

However when I scroll text_widget_1, text_widget_2 does not scroll.

Similarly when I scroll text_widget_2, text_widget_1 does not scroll.

What I want to do is that when I scroll one text widget, the other text widget should also scroll at the same time.

Is there any way to achieve this in tkinter?

It would be great if anyone could help me out.

EDIT: I tried to refer to this question(Python tkinter scrolling two TEXT widgets at the same time with arrow keys), but unfortunately, I couldn't understand what's going in that code, so it didn't help much.

Lenovo 360
  • 569
  • 1
  • 7
  • 27

1 Answers1

4

By default a Text widget has <MouseWheel> bind set. We can override or unbind that sequence. First, we need to know if we want to make that change to all Text widgets or only the a specific one.

  1. If you want to change a <MouseWheel> bind of all text widgets then by using bind_class method and "Text" as the main classname we can do it.

    # Change the binds of all text widgets to that callback function
    text1.bind_class("Text", "<MouseWheel>",  function)
    
  2. But if you only want to change it for one text widget you can it with

    # Change only for a specific Text widget.
    text1.bind_class(text1, "<MouseWheel>",  function)
    

So if you have only these two text widgets (text_widget_1, text_widget_2) then you can use the first option.


def mousewheel(evt):
    text_widget_1.yview_scroll(-1*(evt.delta), 'units') # For MacOS
    text_widget_2.yview_scroll(-1*(evt.delta), 'units') # For MacOS
    
    text_widget_1.yview_scroll(int(-1*(evt.delta/120)), 'units') # For windows
    text_widget_2.yview_scroll(int(-1*(evt.delta/120)), 'units') # For windows

text_widget_1.bind_class("Text", '<MouseWheel>', mousewheel)
...

Or if you have more text widgets but only want to change it for (text_widget_1, text_widget_2) then bind separately, reference 2nd option.

...
text_widget_1.bind_class(text_widget_1, '<MouseWheel>', mousewheel)
text_widget_2.bind_class(text_widget_2, '<MouseWheel>', mousewheel)
...

As I don't know which operating system you are on so I included both scroll settings for windows and macOS, use according to your operating system.

Saad
  • 3,340
  • 2
  • 10
  • 32
  • 1
    Pure brilliance! I never expected such an amazing answer. Thank you so much! – Lenovo 360 Jan 21 '21 at 08:06
  • Could you please explain what does `text_widget_1.yview_scroll(int(-1 * (evt.delta / 120)), 'units')` do ? I'm not much aware of event.delta and yview_scroll, so I just wanted to get it clarified. – Lenovo 360 Jan 21 '21 at 08:06
  • @Lenovo360: It means scrolling the `yveiw` of the widget by 1 unit on 1 scroll. We can tell the scroll to scroll by "pages" instead of "units" also. You can refer to this [question](https://stackoverflow.com/questions/6863921/python-tkinter-canvas-xview-units) for better understanding. – Saad Jan 21 '21 at 08:09
  • Thank you, I understood what is that line for, but I am still having some confusion in `event.delta`. Could you please explain what is `event.delta` and what value does it return? – Lenovo 360 Jan 21 '21 at 08:46
  • 1
    @Lenovo360: `evt` is an instance of [`tkinter.Event`](http://epydoc.sourceforge.net/stdlib/Tkinter.Event-class.html) class which has many attributes one of them is `Event.delta` which only gives `1` and `-1` values. *On down scrolling the value of delta is `-1` and on up scrolling the value is `1`* similarly for right / left scrolling as well. – Saad Jan 21 '21 at 08:53