MM This is for scrolling a canvas like Acrobat Reader does: with the little hand that drags the document.
# canvas_grab_scrolling.tcl -- # # Part of: Useless Widgets Package # Contents: test script for the grab scrolling # Date: Sun Jan 16, 2005 # # Abstract # # Scrolls a canvas by dragging the mouse. This version makes use # of the "scan" widget subcommand, instead of the "scroll" one. # # Copyright (c) 2005 Marco Maggi # # The author hereby grant permission to use, copy, modify, distribute, # and license this software and its documentation for any purpose, # provided that existing copyright notices are retained in all copies # and that this notice is included verbatim in any distributions. No # written agreement, license, or royalty fee is required for any of the # authorized uses. Modifications to this software may be copyrighted by # their authors and need not follow the licensing terms described here, # provided that the new terms are clearly indicated on the first page of # each file where they apply. # # IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHOR HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND # NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, # AND THE AUTHOR AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE # MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # # #page ## ------------------------------------------------------------ ## Setup. ## ------------------------------------------------------------ package require Tcl 8.4 package require Tk 8.4 #page ## ------------------------------------------------------------ ## Widget options. ## ------------------------------------------------------------ option add *borderWidth 1 option add *Canvas.uwp_grab_scroller_grab_cursor fleur option add *Canvas.uwp_grab_scroller_ungrab_cursor hand2 # Possible values: quick_scroll, sticky_mouse, an integer # selecting the "gain" directly (see the canvas man page, # "scan dragto" subcommand). option add *a.uwp_grab_scroller_gain quick_scroll option add *b.uwp_grab_scroller_gain sticky_mouse #page ## ------------------------------------------------------------ ## Main. ## ------------------------------------------------------------ proc main {} { global exit_trigger wm title . "Canvas Grab Scrolling" wm geometry . +200+100 grid [frame .f] -sticky news canvas [set a .f.a] -width 300 -height 300 -background white canvas [set b .f.b] -width 300 -height 300 -background white grid $a $b -sticky news -padx 5 put_rectangles $a put_rectangles $b uwp_grab_scroller_bind $a uwp_grab_scroller_bind $b grid [button .quit -text Exit -command main_exit] focus .quit bind .quit <Return> main_exit bind . <Escape> main_exit interp alias {} main_exit {} set exit_trigger 1 vwait exit_trigger exit } proc put_rectangles { c } { set max [expr {2*[$c cget -width]}] for {set i 0} {$i < 15} {incr i} { $c create rectangle \ [set x [expr {10*$i*2}]] $x [set y [expr {$max-$x}]] $y } $c create line 0 0 $max $max $c create line 0 $max $max 0 $c configure -scrollregion [list 0 0 $max $max] } #page proc uwp_data_set { widget key value } { global uwp_data set uwp_data($widget:$key) $value } proc uwp_data_get { widget key } { global uwp_data return $uwp_data($widget:$key) } proc uwp_p_append_tag { tag widget } { bindtags $widget [linsert [bindtags $widget] end $tag] } proc uwp_p_remove_tag { tag widget } { set idx [lsearch [set ell [bindtags $widget]] $tag] bindtags $widget [lreplace $ell $idx $idx] } proc alias { alias args } { eval { interp alias {} $alias {} } $args } #page bind GrabScroller <ButtonPress-1> { uwp_grab_scroller_event_press %W %x %y } bind GrabScroller <ButtonRelease-1> { uwp_grab_scroller_event_release %W } bind GrabScroller <Enter> { uwp_grab_scroller_event_enter %W } bind GrabScroller <Leave> { uwp_grab_scroller_event_leave %W } bind GrabScrollerScroll <Motion> { uwp_grab_scroller_event_motion %W %x %y } alias uwp_grab_scroller_bind uwp_p_append_tag GrabScroller alias uwp_grab_scroller_unbind uwp_p_remove_tag GrabScroller alias uwp_p_grab_scroller_bind_motion uwp_p_append_tag GrabScrollerScroll alias uwp_p_grab_scroller_unbind_motion uwp_p_remove_tag GrabScrollerScroll #page proc uwp_grab_scroller_event_press { widget x y } { uwp_p_grab_scroller_bind_motion $widget uwp_p_grab_scroller_set_grab_cursor $widget $widget scan mark $x $y } proc uwp_grab_scroller_event_release { widget } { uwp_p_grab_scroller_unbind_motion $widget uwp_p_grab_scroller_set_ungrab_cursor $widget } proc uwp_grab_scroller_event_enter { widget } { uwp_p_grab_scroller_save_current_cursor $widget uwp_p_grab_scroller_set_ungrab_cursor $widget } proc uwp_grab_scroller_event_leave { widget } { uwp_p_grab_scroller_restore_current_cursor $widget } proc uwp_grab_scroller_event_motion { widget x y } { switch -exact -- [set gain [option get $widget uwp_grab_scroller_gain {}]] { sticky_mouse { set gain 1 } quick_scroll { set gain [expr {[winfo width $widget]/8}] } default { if { [string length $gain] == 0 } { set gain 10 } } } $widget scan dragto $x $y $gain } proc uwp_p_grab_scroller_save_current_cursor { widget } { uwp_data_set $widget oldCursor [. cget -cursor] } proc uwp_p_grab_scroller_restore_current_cursor { widget } { . configure -cursor [uwp_data_get $widget oldCursor] } proc uwp_p_grab_scroller_set_grab_cursor { widget } { . configure -cursor [option get $widget uwp_grab_scroller_grab_cursor {}] } proc uwp_p_grab_scroller_set_ungrab_cursor { widget } { . configure -cursor [option get $widget uwp_grab_scroller_ungrab_cursor {}] } #page ## ------------------------------------------------------------ ## Let's go. ## ------------------------------------------------------------ main ### end of file # Local Variables: # mode: tcl # End:
KPV: There's an easier way of doing almost the exact interaction--just use the bindings that the text widget uses to scrolling via mouse button 2.
canvas .c bind .c <2> [bind Text <2>] bind .c <B2-Motion> [bind Text <B2-Motion>]
anoved: Another simple way to scroll canvas .c with the mouse is:
bind .c <ButtonPress-1> {%W scan mark %x %y} bind .c <B1-Motion> {%W scan dragto %x %y 1}
JG: Thanks ... that's exactly what I was looking for ...
MaxPerl - 2019-11-24 02:36:07
For touchscreens it is important, to bind <B1-Motion> in the callback function of <ButtonPress-1> event and unbind it, when a <ButtonRelease-1> event occurs. Otherwise it happens, that the scan dragto command is fired before the last scan mark command could be processed... With only Mouse dragging, I didn't notice this problem...