multi scrolling

ulis, 2003-07-02: How to scroll two widgets at the same time. Or: synchronized listboxes.

Also see mention of the same subject in the FAQ for Tk.


  # ---------------
  # multi scrolling
  # ---------------
  
  # creating the widgets
  frame .f
  foreach n {0 1 2 3 4 5 6 7 8 9} { lappend list1 item1-$n }
  foreach n {0 1 2 3 4 5 6 7 8 9} { lappend list2 item2-$n }
  listbox .f.lb1 -list ::list1 -height 8 -yscrollc yset
  listbox .f.lb2 -list ::list2 -height 8 -yscrollc yset
  scrollbar .f.sb -command yview
  # placing & showing the widgets
  pack .f
  grid .f.lb1 -row 0 -column 0
  grid .f.lb2 -row 0 -column 1
  grid .f.sb -row 0 -column 2 -sticky ns
  # the scroll procs
    # called by a listbox
  proc yset {args}  {
    eval [linsert $args 0 .f.sb set]
    yview moveto [lindex [.f.sb get] 0]
  }
    # called by the scroll bar
  proc yview {args}  {
    eval [linsert $args 0 .f.lb1 yview]
    eval [linsert $args 0 .f.lb2 yview]
  }

Or rewritten to use {*}:

# called by a listbox
proc yset {args} {
    .f.sb set {*}$args
    yview moveto [lindex [.f.sb get] 0]
}
# called by the scroll bar
proc  yview {args} {
    .f.lb1 yview {*}$args
    .f.lb2 yview {*}$args
}

JMD, 2006-06-13, Just to clarify, this technique does work with other widgets, such as horizontally scrolling a text box and an entry field (using xview and xset, of course).


ulis, 2003-08-05: Better to have the selection synchronized.

  # ---------------
  # multi selecting
  # ---------------

  # creating the widgets
  foreach n {0 1 2 3 4 5 6 7 8 9} { lappend list1 item1-$n }
  foreach n {0 1 2 3 4 5 6 7 8 9} { lappend list2 item2-$n }
  frame .f -relief sunken -bd 2 -highlightt 0
  listbox .f.lb1 -list ::list1 -height 8 -yscrollc yset \
    -relief flat -selectbord 0 -highlightt 0 -bd 0 \
    -exportselection 0
  listbox .f.lb2 -list ::list2 -height 8 -yscrollc yset \
    -relief flat -selectbord 0 -highlightt 0 -bd 0 \
    -exportselection 0
  canvas .f.c -width 1 -height 0 -relief flat -selectbord 0 -highlightt 0 -bd 0
  scrollbar .f.sb -command yview
  # placing & showing the widgets
  pack .f
  grid .f.lb1 -row 0 -column 0
  grid .f.c -row 0 -column 1
  grid .f.lb2 -row 0 -column 2
  grid .f.sb -row 0 -column 3 -sticky ns
  # the scroll procs
    # called by a listbox
  proc yset {args}  {
    eval [linsert $args 0 .f.sb set]
    yview moveto [lindex [.f.sb get] 0]
  }
    # called by the scroll bar
  proc yview {args}  {
    eval [linsert $args 0 .f.lb1 yview]
    eval [linsert $args 0 .f.lb2 yview]
  }
  # bind to the select events
  bind .f.lb1 <<ListboxSelect>> { synchro .f.lb1 .f.lb2 }
  bind .f.lb2 <<ListboxSelect>> { synchro .f.lb2 .f.lb1 }
  proc synchro {w1 w2}  {
    set sel [$w1 cursel]
    $w2 selection clear 0 end
    foreach item $sel { $w2 selection set $item }
  }

See Also:

scrollsync widget of the Scrollutil package