[Tkinter-discuss] scrolling more widgets with one scrollbar

Michael Lange klappnase at web.de
Thu Feb 3 11:56:35 CET 2011


Hi,

Thus spoketh "Martin B." <spooky.ln at tbs-software.com> 
unto us on Tue, 1 Feb 2011 16:16:56 +0100:

> Hi all,
> I need scroll 3 Text widgets with one scrollbar.
> All is packed into grid [text, text, text, scrollbar]
> 
> all Text widgets have font on same size
> how i scroll all 3 widgets 'synced' using scrollbar ?
> 
> i have a method which is scrollbar.command
> 
> def update_widgets(self, *args):
> 	# scrolling all 3 widgets
> 	for win in self.textwindows:
> 		win.yview_moveto(args[1])
> 
> this scrolling widgets but after few 'slides' rows are not synced :(

I'd replace this with something like:

def update_widgets(self, *args):
    for win in self.textwindows:
        win.yview(*args)

If this still doesn't work properly, i would try and add an
update_idletasks() to the function. At least here this does not seem to
be necessary though.

> 
> and second question is 'how i set next 2 widgets and scrollbar if i
> scroll some widget using keyboard? '

This appears to be a lot more tricky ;)
These key bindings are defined in the file text.tcl and I am afraid in order
to properly set up synchrounous scrolling you will have to dig yourself
through this and add appropriate callbacks to all of the default bindings
for Up, Down, Prior, Next ... keys and some mouse events.
Fortunately this doesn't seem to be too hard once you understand how this
works:

For example, the binding for the <Down> event on the tcl level looks like
this (%W replaces the widget taht receives the event here):

bind Text <Down> {
    tk::TextSetCursor %W [tk::TextUpDownLine %W 1]
}

In order to "translate" this into python, you will have to use the
widget's tk.call() magic (it does not matter which is the "calling"
widget here). First check the return value of the embedded tk command and
then pass it to the outer tk command:

    x = root.tk.call('tk::TextUpDownLine', textwidget, 1)
    root.tk.call('tk::TextSetCursor', textwidget, x)

I set up a minimal example that shows how to use this technique to set up
modified key bindings that allow to scroll two text widgets synchronously
with the Up and Down keys:

###########################################
from Tkinter import *

root = Tk()
t1 = Text(root, height=20, width=40)
t1.pack(side='left')
t2 = Text(root, height=20, width=40)
t2.pack(side='left')

# add some text to scroll
f = open(__file__, 'r')
text = f.read()
f.close()
t1.insert('end', text)
t2.insert('end', text)

def yview(*args):
    t1.yview(*args)
    t2.yview(*args)

sb = Scrollbar(root, command=yview)
sb.pack(side='right', fill='y')

t1.configure(yscrollcommand=sb.set)
t2.configure(yscrollcommand=sb.set)

slave = {t1: t2, t2: t1}
for t in (t1, t2):
    def down(event):
        root.tk.call('tk::TextSetCursor', slave[event.widget],
                root.tk.call('tk::TextUpDownLine', event.widget, 1))
    t.bind('<Down>', down, add=True)
    def up(event):
        root.tk.call('tk::TextSetCursor', slave[event.widget],
                root.tk.call('tk::TextUpDownLine', event.widget, -1))
    t.bind('<Up>', up, add=True)

root.mainloop()
###########################################

I hope this helps

Michael

.-.. .. ...- .   .-.. --- -. --.   .- -. -..   .--. .-. --- ... .--. . .-.

You'll learn something about men and women -- the way they're supposed
to be.  Caring for each other, being happy with each other, being good
to each other.  That's what we call love.  You'll like that a lot.
		-- Kirk, "The Apple", stardate 3715.6


More information about the Tkinter-discuss mailing list