Home > Archive > Tcl > August 2004 > how to trigger event by moving the view of a canvas
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
how to trigger event by moving the view of a canvas
|
|
| Svenn Are Bjerkem 2004-08-24, 4:43 pm |
| Hi,
I have been looking for a way to trigger an event when a canvas is being
moved. The viewport to the canvas can be moved with the arrow buttons,
and that is an easy bind. Now I add horizontal and vertical scrollbars
to move around in the viewport and that is also easy. I was then looking
for a way to trigger a function that draws a grid in that viewport each
time the canvas is moved independent of how it moves. So far I have had
to put a call to the grid redraw function in the bound scripts for the
buttons. Problem is the scrollbars: the -command {.canvas set} cannot be
written -command {.canvas set ;grid_redraw} because of the concatenating
of the arguments to -command.
Now the question: There are many events to bind to, but is there an
event for a change of viewport for a canvas?
--
Svenn
| |
| Bryan Oakley 2004-08-24, 11:06 pm |
| Svenn Are Bjerkem wrote:
> Hi,
> I have been looking for a way to trigger an event ... So far I have had
> to put a call to the grid redraw function in the bound scripts for the
> buttons. Problem is the scrollbars: the -command {.canvas set} cannot be
> written -command {.canvas set ;grid_redraw} because of the concatenating
> of the arguments to -command.
>
There's no reason you have to call the canvas set command directly.
Create a helper proc that does any extra work you need, sort of like this:
scrollbar .s -command {myCanvasSet .canvas}
proc myCanvasSet {w args} {
# call the canvas set command; save the result
set result [eval \$w set $args]
# do any extra work
grid_redraw
# return the result from the set command
# (the scrollbar requires it...)
return $result
}
Alternately, do something similar with the xview and yview commands of
the canvas so that no matter what causes the view to change, your grid
gets redrawn:
canvas .canvas \
-yscrollcommand {canvas_yscroll} \
-xscrollcommand {canvas_xscroll}
proc canvas_yscroll {args} {
eval .scrollbar $args
grid_redraw
}
I'm sure I got some of the details wrong, but hopefully you get the
idea. The point being, just because scrollbars and widgets are typically
tied directly together there's no reason why that has to be so; it's
easy to put a proc in the middle that does extra work whenever something
changes.
| |
| Svenn Are Bjerkem 2004-08-25, 3:58 pm |
| Hi Bryan, you basically understood my needs.
In article <UWNWc.12887$Z32.6578@newssvr22.news.prodigy.com>,
Bryan Oakley <oakley@bardo.clearlight.com> wrote:
> scrollbar .s -command {myCanvasSet .canvas}
> proc myCanvasSet {w args} {
> # call the canvas set command; save the result
if I insert a puts "$w $args" here I can see that proper arguments are
passed into the function.
> set result [eval \$w set $args]
> # do any extra work
If I put in a puts "$result" here, there is nothing written to stdout.
> grid_redraw
> # return the result from the set command
> # (the scrollbar requires it...)
> return $result
> }
There is no movement of the canvas when I move the scrollbar.
>
> Alternately, do something similar with the xview and yview commands of
> the canvas so that no matter what causes the view to change, your grid
> gets redrawn:
>
> canvas .canvas \
> -yscrollcommand {canvas_yscroll} \
> -xscrollcommand {canvas_xscroll}
>
> proc canvas_yscroll {args} {
> eval .scrollbar $args
I get an error message from my app that 0.9873 is not a valid argument.
> grid_redraw
> }
>
Thanks for your suggestions. I'll take a bit deeper look into what those
evals do and see if I can reproduce the errors on a linux and a windows
box. I am currently using AquaTcl 8.4 on Macosx
Kind regards,
--
Svenn
| |
| Bryan Oakley 2004-08-25, 8:57 pm |
| Svenn Are Bjerkem wrote:
> Hi Bryan, you basically understood my needs.
>
> ...
> There is no movement of the canvas when I move the scrollbar.
>
>
The point wasn't for you to cut and paste my code in. The point was for
you to see how you can have the -yscrollcommand of a canvas, or the
-command of a scrollbar can call a proc. But that's my mistake, not yours.
Here's code you can cut and paste. First, lets start off with the
traditional way of connecting a canvas and scrollbar:
canvas .c \
-width 400 -height 400 \
-scrollregion {0 0 400 1000}
scrollbar .sb
..c create rectangle 100 100 300 300 -fill red
pack .sb -side right -fill y
pack .c -side left -fill both -expand 1
..c configure -yscrollcommand {.sb set}
..sb configure -command {.c yview}
When you do something like "-yscrollcommand {.sb set}" it's doing not
much more than telling the tcl interpreter "when you scroll, eval this
command with some additional arguments". So, as long as sometime during
the processing of the -yscrollcommand we do that, all should be fine.
Knowing that, we can change the widgets to call procs rather than each
other. The easiest way is to keep the commands the same but put our proc
as the first command and leave everything else; that way we just shove
everything into an eval and we're good.
It's important to remember that because tk appends additional arguments
to these commands; we need to account for them. That is why I use the
catch-all "args" argument rather than something more explicit. You can,
of course, add any additional arguments that you want.
Here I add a puts statement so that you can observe the new behavior
that happens in addition to the normal scrolling.
proc yscroll {w args} {
puts "yscroll: w=$w args=$args"
eval $w $args
}
proc sscroll {w args} {
puts "sscroll: $w args=$args"
eval $w $args
}
Now that we have the procs, lets use them rather than connecting the
widgets together directly:
..c configure -yscrollcommand {yscroll .sb set}
..sb configure -command {sscroll .c yview}
If all goes well, the canvas still scrolls but you also see output on
stdout (or in the console if running that way...).
|
|
|
|
|