Code Comments
Programming Forum and web based access to our favorite programming groups.While self-learning tcl/tk, I met a strange situation when I tried to
move a line (assigned with a tag "movable") that is on top of another
item in the canvas (e.g. a rectangle, with or without assigning a
different tag). The problem is after I bind the line with ".cancas
bind movable <Button-1> {canvasMark %x %y .canvas}" and ".canvas bind
movable <B1-Motion> {canvasDrag %x %y .canvas}", I can drag the line
only when the cursor is exactly on the line. When the cursor is
slightly off, guess what, the other item (e.g. the rectangle) was
moved instead, which was assigned a different tag!?
This may sounds silly but I'm really appreciated if someone can help
me out with this puzzle.
Post Follow-up to this messageselflearner wrote:
> While self-learning tcl/tk, I met a strange situation when I tried to
> move a line (assigned with a tag "movable") that is on top of another
> item in the canvas (e.g. a rectangle, with or without assigning a
> different tag). The problem is after I bind the line with ".cancas
> bind movable <Button-1> {canvasMark %x %y .canvas}" and ".canvas bind
> movable <B1-Motion> {canvasDrag %x %y .canvas}", I can drag the line
> only when the cursor is exactly on the line. When the cursor is
> slightly off, guess what, the other item (e.g. the rectangle) was
> moved instead, which was assigned a different tag!?
>
> This may sounds silly but I'm really appreciated if someone can help
> me out with this puzzle.
what does the code in canvasMark, canvasDrag look like?
what id/tag are you using ion you canvas move command?
my guess is you are using "current", which (as you have
seen) isn't guaranteed to be the one that triggered the
action in the first place. you can do a couple of things
be more explicit: instead of binding to the tag, bind to
each item directly, and include in the bind command the
exact ID and use that in the move command.
be more carful in action: still bind only to the tag, but in
your canvasMark proc use check the current item for the movable
tag, if it doesn;t have it - use find to get the nearest item
with a movable tag on it.
Hope this helps, also check out the wiki, it has many good examples
of various things and a useful learning aid.
Bruce
Post Follow-up to this messageThanks for the tips. I tried to use item ID with binding, same problem. However, when I use "withtag" to replace "closest" option in "find" commmand, it works! Then when I have more than one item with the same tag name, I can't choose only one (e.g. the closest item to cursor). Apparently I can not use more than one searchspec in "find" command. Thanks again for the rapid reply! On Apr 2, 2:06 pm, Bruce Hartweg <bruce-n...@hartweg.us> wrote: > selflearner wrote: > > > what does the code in canvasMark, canvasDrag look like? > what id/tag are you using ion you canvas move command? > my guess is you are using "current", which (as you have > seen) isn't guaranteed to be the one that triggered the > action in the first place. you can do a couple of things > > be more explicit: instead of binding to the tag, bind to > each item directly, and include in the bind command the > exact ID and use that in the move command. > > be more carful in action: still bind only to the tag, but in > your canvasMark proc use check the current item for the movable > tag, if it doesn;t have it - use find to get the nearest item > with a movable tag on it. > > Hope this helps, also check out the wiki, it has many good examples > of various things and a useful learning aid. > > Bruce
Post Follow-up to this messageOn Apr 2, 8:06=A0pm, Bruce Hartweg <bruce-n...@hartweg.us> wrote: > selflearner wrote: > > be more explicit: instead of binding to the tag, bind to > each item directly, and include in the bind command the > exact ID and use that in the move command. About this idiom, I have always felt a bit of frustration, since it wastes the elegance of tags and forces to bind N different scripts for N items. Instead, it would be natural to have a %-sequence (eg "%I") holding the ID of the item receiving the event (I know percents are widget-type-agnostic so far, and this would break the tradition, but the benefit seems worth it). Has this ever been considered ? -Alex
Post Follow-up to this messageOn Apr 2, 9:15=A0pm, selflearner <chenzhen1...@gmail.com> wrote: > Thanks for the tips. I tried to use item ID with binding, same > problem. However, when I use "withtag" to replace "closest" option in > "find" commmand, it works! Then when I have more than one item with > the same tag name, I can't choose only one (e.g. the closest item to > cursor). Apparently I can not use more than one searchspec in "find" > command. Help us help you: don't limit yourself to vague descriptions and interpretations, post the code of your two procedures as Bruce asked you. Regarding the implementation of simple click-and-drag, I don't see a compelling reason to use [find closest] or [find withttag] within the callbacks: - the click callback is already "curried" with an id as Bruce suggested - this callback also sets a global or namespace variable to the id under consideration - the drag callback just moves the object with the stored id This is much safer than depending of [find closest] which may sometimes hit an unwanted item if the target is thin, small, or hollow. -Alex
Post Follow-up to this messageAlexandre Ferrieux wrote: > On Apr 2, 8:06 pm, Bruce Hartweg <bruce-n...@hartweg.us> wrote: > > About this idiom, I have always felt a bit of frustration, since it > wastes the elegance of tags and forces to bind N different scripts for > N items. Instead, it would be natural to have a %-sequence (eg "%I") > holding the ID of the item receiving the event (I know percents are > widget-type-agnostic so far, and this would break the tradition, but > the benefit seems worth it). Has this ever been considered ? > I don't know, but I would support it. as far as the type agnostic thing this wouldn't apply to the global any widget bind command, but the specific bind sub-command so saying "canvas bind" has the same sequences as the standard bind and additionally support %I that is replaced with the item id would be fine IMHO. Sounds like time for a feature request and/or TIP ;) Bruce
Post Follow-up to this messageselflearner wrote: > Thanks for the tips. I tried to use item ID with binding, same > problem. However, when I use "withtag" to replace "closest" option in > "find" commmand, it works! Then when I have more than one item with > the same tag name, I can't choose only one (e.g. the closest item to > cursor). Apparently I can not use more than one searchspec in "find" > command. yes you can - just need to get the syntax right. Also - can you post the code where you used the ID that didn't work? we could help figure out what went wrong as that should work. Also - take a look at the standard tk demo the simple canvas demo does exactly what you want - you can see a nice example of how it was done. Bruce
Post Follow-up to this messageI basically copied Welch's example of adding items to canvas. Here are
the codes which works when I have only one line. When there are two
lines with the same tag name, I think the list now have two elements
that won't work with "move", and I won't be able to add "closest $x
$y" within the "find" command:
canvas .c -bg white -width 300 -height 200 -scrollregion {0 0 700 400}
\
-xscrollcommand [list .xscroll set] -yscrollcommand [list .yscroll
set]
scrollbar .xscroll -orient horizontal -command [list .c xview]
scrollbar .yscroll -orient vertical -command [list .c yview]
grid .c .yscroll -sticky news
grid .xscroll -sticky ew
grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1
.c create rect 10 10 50 50 -fill red
.c create line 1 1 40 40 90 60 -width 2 -tags movline
.c create line 10 10 40 50 60 30 -fill blue -width 2 -tags movline
.c bind movline <Button-1> {canvasMark %x %y .c}
#.c bind movline <B1-Motion> {canvasDrag %x %y .c}
proc canvasMark { x y can} {
global canvas
set x [$can canvasx $x]
set y [$can canvasy $y]
set canvas($can,obj) [$can find withtag movline]
set canvas($can,x) $x
set canvas($can,y) $y
}
proc canvasDrag { x y can} {
global canvas
set x [$can canvasx $x]
set y [$can canvasy $y]
set dx [expr $x - $canvas($can,x)]
set dy [expr $y - $canvas($can,y)]
$can move $canvas($can,obj) $dx $dy
set canvas($can,x) $x
set canvas($can,y) $y
}
Post Follow-up to this messageOn Apr 2, 9:29=A0pm, Bruce Hartweg <bruce-n...@hartweg.us> wrote: > Alexandre Ferrieux wrote: > > > > I don't know, but I would support it. as far as the type agnostic thing > this wouldn't apply to the global any widget bind command, but the > specific bind sub-command so saying "canvas bind" =A0has the same sequence=[/color ] s > as the standard bind and additionally support %I that is replaced with > the item id would be fine IMHO. Yes. And the same could be done to character positions in text widgets (since they must be computed at event dispatch time because of tag bindings). For the implementation, I'm just now discovering that part of Tk, but it looks like all three flavours of bind (toplevel command and canvas/ text subcommands) use Tk_CreateBinding, so in order to do widget- specific things some kind of polymorphic behavior must be defined. It is definitely doable, for example with yet another function pointer field. > > Sounds like time for a feature request and/or TIP ;) I would be delighted if you could take over (yes, it was a bait ;-) (I would love to write the patch but I need a few more hours of reverse engineering first ;-) Alternatively, others are welcome to step forth and express agreement (or not) ! -Alex
Post Follow-up to this messageOn Apr 2, 3:34 pm, Bruce Hartweg <bruce-n...@hartweg.us> wrote:
> yes you can - just need to get the syntax right.
you mean the syntax to allow more than one searchspec in "find"?
>
> Also - can you post the code where you used the ID that didn't work?
> we could help figure out what went wrong as that should work.
refer to the code, I just set a variable to the creation of line as
follow:
set lineID [.c create line 1 1 40 40 90 60 -width 2]
.c bind $lineID <Button-1> {canvasMark %x %y .c}
> Also - take a look at the standard tk demo the simplecanvasdemo
> does exactly what you want - you can see a nice example of how it was done.[/color
]
I would be really appreciated if you can give me the direct link
because there are just so many of them!
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.