Partial display of canvas widget

3 views
Skip to first unread message

David Peebles

unread,
May 18, 1999, 3:00:00 AM5/18/99
to
Hi ticklers,

I want to use a canvas widget to display a set of canvas objects (lines,
bitmaps etc.). However, I require the main part of the canvas to be blank to
the user, with only a specific rectangular portion of the canvas visible at
any one time. The location of this rectangular portion is to be determined
by the user who can change its position by moving the mouse. Only the canvas
objects under this rectangular portion are to be seen by the user at any one
time but these must change as the rectangle is moved by the user so that the
complete set of canvas objects can be seen if the rectangle is moved about
the canvas. I hope this is clear. To illustrate, A (below) is the canvas
widget with the canvas objects and B is a portion of the canvas visible to
the user within a movable rectangle.

A__________ B__________
| : | | |
| : <> | | |
| : | | ___ |
| |__ <> | | | <>| |
| | ## | | |__#| |
|__________| |__________|

Has anybody any ideas how this can be efficiently done or can anyone point
me in the direction of an existing application which has this feature?

Many thanks in advance,

David Peebles

==================================================================
Dr David Peebles
Artificial Intelligence Group,
Department of Psychology, University of Nottingham,
University Park, Nottingham, NG7 2RD, UK.

email: d...@psychology.nottingham.ac.uk
tel: 0 115 951 5308
fax: 0 115 951 5324
international: +44 115 951 ----
url: http://www.psychology.nottingham.ac.uk/staff/David.Peebles/
==================================================================

D. Richard Hipp

unread,
May 18, 1999, 3:00:00 AM5/18/99
to
David Peebles wrote:
>
> I want to use a canvas widget to display a set of canvas objects (lines,
> bitmaps etc.). However, I require the main part of the canvas to be blank to
> the user, with only a specific rectangular portion of the canvas visible at
> any one time.... [Complete text below]

The first technique that comes to my mind is to use the "place"
geometry manager with a clipping window.

Begin by creating an outer frame that is the size of your
canvas:

frame .f -width 640 -height 480
pack .f

Next make a clipping window as a child of the outer frame
and make the size of the clipping window be the size of the
visible part of your canvas.

frame .f.f -width 100 -height 100

Finally, generate a canvas which is the size of the outer
frame, but which is a child of the clipping window.

canvas .f.f.c -width 640 -height 480 -bd 0 \
-highlightthickness 0

Now "place" the clipping window somewhere in the middle
of the outer frame:

place .f.f -x 300 -y 200

Finally, "place" the canvas so that it overlays the outer
window:

place .f.f.c -x -300 -width 640 -y -200 -height 480

Notice that the x and y coordinates of .f.f.c are the negative
of the corrdinates of the clipping window. This causes the
upper left corner of the canvas to always correspond exactly
to the upper left corner of .f.

(Using the "-in" parameter to place seems like a slightly
easier approach, but it doesn't appear to work as advertised.
Is this a bug?)

Now all you have to do is rig things so that the "place" of
the clipping window moves around according to your mouse actions.
You didn't specify what mouse actions would do the moving, so
I can't be more specific.

proc MoveClippingWindow {x y} {
place .f.f -x $x -y $y
place .f.f.c -x -$x -y -$y
}

Hope this gets you started.

Anybody have a better idea?

David Peebles wrote:
>
> I want to use a canvas widget to display a set of canvas objects (lines,
> bitmaps etc.). However, I require the main part of the canvas to be blank to
> the user, with only a specific rectangular portion of the canvas visible at
> any one time. The location of this rectangular portion is to be determined
> by the user who can change its position by moving the mouse. Only the canvas
> objects under this rectangular portion are to be seen by the user at any one
> time but these must change as the rectangle is moved by the user so that the
> complete set of canvas objects can be seen if the rectangle is moved about
> the canvas. I hope this is clear. To illustrate, A (below) is the canvas
> widget with the canvas objects and B is a portion of the canvas visible to
> the user within a movable rectangle.
>
> A__________ B__________
> | : | | |
> | : <> | | |
> | : | | ___ |
> | |__ <> | | | <>| |
> | | ## | | |__#| |
> |__________| |__________|
>
> Has anybody any ideas how this can be efficiently done or can anyone point
> me in the direction of an existing application which has this feature?

--
D. Richard Hipp -- d...@acm.org -- http://www.hwaci.com/drh/

D. Richard Hipp

unread,
May 18, 1999, 3:00:00 AM5/18/99
to
David Peebles wrote:
>
> I want to use a canvas widget to display a set of canvas objects (lines,
> bitmaps etc.). However, I require the main part of the canvas to be blank to
> the user, with only a specific rectangular portion of the canvas visible at
> any one time. The location of this rectangular portion is to be determined
> by the user who can change its position by moving the mouse. Only the canvas
> objects under this rectangular portion are to be seen by the user at any one
> time but these must change as the rectangle is moved by the user so that the
> complete set of canvas objects can be seen if the rectangle is moved about
> the canvas. I hope this is clear. To illustrate, A (below) is the canvas
> widget with the canvas objects and B is a portion of the canvas visible to
> the user within a movable rectangle.
>
> A__________ B__________
> | : | | |
> | : <> | | |
> | : | | ___ |
> | |__ <> | | | <>| |
> | | ## | | |__#| |
> |__________| |__________|
>

Sample code is follows:

# The outer frame. (Make it blue. The clipping window will appear
# light gray.)
#
frame .f -width 600 -height 400 -bg skyblue
pack .f

# The clipping window.
#


frame .f.f -width 100 -height 100

# The canvas.
canvas .f.f.c -width 600 -height 400 -bd 0 -highlightthickness 0

# Put something in the canvas so we can see it.
#
for {set y 0} {$y<400} {incr y 25} {
set x [expr int($y*550.0/350.0)]
.f.f.c create text $x $y -text {Hello!} -anchor nw
.f.f.c create text [expr 550-$x] $y -text {Hi There!} -anchor nw
}

# Move the clipping window to $x,$y
#
proc moveit {x y} {
if {$x<0} {set x 0}
if {$x>500} {set x 500}
if {$y<0} {set y 0}
if {$y>300} {set y 300}


place .f.f -x $x -y $y
place .f.f.c -x -$x -y -$y

global clipX clipY
set clipX $x
set clipY $y
}
moveit 0 0

# Bindings to drag the clipping window using button 1.
#
bind .f.f.c <ButtonPress-1> {
set offsetX [expr %x-$clipX]
set offsetY [expr %y-$clipY]
}
bind .f.f.c <B1-Motion> {
moveit [expr %x-$offsetX] [expr %y-$offsetY]

Roy Terry

unread,
May 18, 1999, 3:00:00 AM5/18/99
to
_Very_ nifty. On Win95, it seemed to require an
update idletasks after the movit call.

Bryan Oakley

unread,
May 18, 1999, 3:00:00 AM5/18/99
to

D. Richard Hipp <d...@acm.org> wrote in message
news:3741DD8C...@acm.org...

> David Peebles wrote:
> >
> > I want to use a canvas widget to display a set of canvas objects (lines,
> > bitmaps etc.).
[snip]

> Sample code is follows:

[snip]

Wow. What a wonderful solution. That is just absolutely fabulous! This
little bit of code should make it into the widget demo. Short, simple, and
dramatic. Very cool. I never would have thought of this solution. It
instantly made me think of the pad++ magic lenses, and I could see how one
might implement them using a variation of this technique.

Is this something you use in production code? I'm curious how well it scales
to canvases with a lot of objects, or really large canvases. I notice my
little CPU meter pretty well pegs itself while I move things around, but the
movement itself seems pretty smooth with only a small bit of jerkiness (on
NT).


Bryan Oakley

unread,
May 18, 1999, 3:00:00 AM5/18/99
to
Roy Terry <royt...@earthlink.net> wrote in message
news:3741F150...@earthlink.net...

> _Very_ nifty. On Win95, it seemed to require an
> update idletasks after the movit call.

Hmmm. Not on NT. Interesting.


Roy Terry

unread,
May 19, 1999, 3:00:00 AM5/19/99
to Bryan Oakley

Bryan Oakley wrote:
>
> Roy Terry <royt...@earthlink.net> wrote in message
> news:3741F150...@earthlink.net...

> > _Very_ nifty. On Win95, it seemed to require an

> > update idletasks after the movit call.

I withdraw this comment.

It did seem to require the update at first try. On retest it works
fine. That first try was using tkcon 1.6 and responding yes when
it asked me to retry after loading tk. Perhaps a glitch in the
retry somehow?

Darren New

unread,
May 19, 1999, 3:00:00 AM5/19/99
to
Way cool! I don't understand how it works, so I guess it's time to go
read canvas.n again. :-) But I did forward it on to someone whose
software has a truely crufty UI, MSWindows patched on top of a decent
CLI, trying to get them to fix their UI with the throw-away-and-replace
technique. :-)

--
Darren New / Senior Software Architect / MessageMedia, Inc.
San Diego, CA, USA (PST). Cryptokeys on demand.
Help outlaw Hydrogen Dioxide, a major component of acid rain!

Donal K. Fellows

unread,
May 21, 1999, 3:00:00 AM5/21/99
to
In article <7hsh9l$nla$1...@oyez.ccc.nottingham.ac.uk>,

David Peebles <d...@psychology.nottingham.ac.uk> wrote:
> A__________ B__________
> | : | | |
> | : <> | | |
> | : | | ___ |
> | |__ <> | | | <>| |
> | | ## | | |__#| |
> |__________| |__________|
>
> Has anybody any ideas how this can be efficiently done or can anyone point
> me in the direction of an existing application which has this feature?

You can do this (and more complex stuff) *on*UNIX/X*systems* using a
little extension I wrote that allows you to clip a window to any shape
you want, including non-rectangular shapes. Included in the
distribution is a little example script that lets you put a grubby
fingerprint on the screen, and another that has a piece of text traced
out by some animated lines behind it.

http://www.cs.man.ac.uk/~fellowsd/tcl/#scripts/shape

Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ fell...@cs.man.ac.uk
-- The small advantage of not having California being part of my country would
be overweighed by having California as a heavily-armed rabid weasel on our
borders. -- David Parsons <o r c @ p e l l . p o r t l a n d . o r . u s>

Reply all
Reply to author
Forward
0 new messages