Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tk problem: resizable canvas with scrollbars (and size grip- like thing) within another canvas

679 views
Skip to first unread message

sebs...@gmail.com

unread,
Feb 10, 2014, 8:17:44 PM2/10/14
to
Hi,
I'm new to tcl/tk and I'm working on a project where I want to have a resizable canvas (the user should be able to resize it with something like sizegrip). I've googled about for a long time and couldn't find anything helpful, I've come pretty close but I feel like I don't have a completely solid understanding of how bind interacts with various windows. here's what I have so far. The problem seems to be when the mouse jumps into the red area during fast movement. How should I deal with the focus stealing of the new window?

Thanks much

tk::canvas .c -scrollregion "0 0 1000 1000" -yscrollcommand ".v set" -xscrollcommand ".h set" -bg blue -highlightthickness 0
grid .c -sticky nwes -column 0 -row 0
grid columnconfigure . 0 -weight 1
grid rowconfigure . 0 -weight 1

grid [tk::scrollbar .h -orient horizontal -command ".c xview"] -column 0 -row 1 -sticky we
grid [tk::scrollbar .v -orient vertical -command ".c yview"] -column 1 -row 0 -sticky ns
grid [ttk::sizegrip .sz] -column 1 -row 1 -sticky se

ttk::frame .c.test
set pressed 0
canvas .c.test.canvas -scrollregion "0 0 1000 1000" -yscrollcommand ".c.test.v set" -xscrollcommand ".c.test.h set" -bg red -highlightthickness 0

grid .c.test.canvas -sticky nwes -column 0 -row 0
grid [tk::scrollbar .c.test.h -orient horizontal -command ".c.test.canvas xview"] -column 0 -row 1 -sticky we
grid [tk::scrollbar .c.test.v -orient vertical -command ".c.test.canvas yview"] -column 1 -row 0 -sticky ns
#grid [ttk::sizegrip .c.test.sz] -column 1 -row 1 -sticky se
grid columnconfigure .c.test 0 -weight 1
grid rowconfigure .c.test 0 -weight 1
set windowid [.c create window 40 40 -window .c.test -anchor nw -width 100 -height 100]

proc destroyall {} {
foreach w [winfo children .] {
destroy $w
}
}

bind . <B1-Motion> {

global windowid; global xcoord; global ycoord; global pressed

if {$pressed} {
puts "motion called, pressed"
set changex [expr [winfo pointerx .] - $xcoord + [.c itemcget $windowid -width]]
set changey [expr [winfo pointery .] - $ycoord + [.c itemcget $windowid -height]]
.c itemconfigure $windowid -width $changex -height $changey
set xcoord [winfo pointerx .]; set ycoord [winfo pointery .]
} else {puts "motion called"}
}

bind . <ButtonRelease-1> {
puts "button not pressed anymore"
set pressed 0
}

bind .c.test <ButtonPress-1> {
global xcoord; global ycoord; global pressed
set xcoord [winfo pointerx .]; set ycoord [winfo pointery .]
set pressed 1
focus .c.test
puts "button pressed"
#puts $xcoord
#puts $ycoord
}

Rich

unread,
Feb 11, 2014, 4:36:33 PM2/11/14
to
sebs...@gmail.com wrote:
: Hi,
: I'm new to tcl/tk and I'm working on a project where I want to
: have a resizable canvas (the user should be able to resize it
: with something like sizegrip). I've googled about for a long
: time and couldn't find anything helpful, I've come pretty close
: but I feel like I don't have a completely solid understanding of
: how bind interacts with various windows. here's what I have so
: far. The problem seems to be when the mouse jumps into the red
: area during fast movement. How should I deal with the focus
: stealing of the new window?

Are you aware of the ttk::sizegrip widget?

I.e,:

canvas .c -borderwidth 2 -relief solid

grid .c -sticky news

ttk::sizegrip .sg

grid .sg -row 1 -column 1

grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1

Grab the grip in the bottom right corner with the mouse, pull it
around, the window resizes.

Seb Shader

unread,
Feb 11, 2014, 6:04:22 PM2/11/14
to
thanks for the reply
yes, in fact I used it in the example above for the top-level window. However it doesn't seem to work in windows that aren't top-level? I think the documentation mentions that , and I experienced some real oddities when I attempted to use it on the window within the canvas, (such as moving the top level window's size grip and having the window on the canvas resize by whatever factor it moved by)

I may attempt to make my own size grip with yet another canvas but I have yet to see if/how this would work.

Rich

unread,
Feb 11, 2014, 11:30:48 PM2/11/14
to
sebs...@gmail.com wrote:
: Hi,
: I'm new to tcl/tk and I'm working on a project where I want to
: have a resizable canvas (the user should be able to resize it
: with something like sizegrip). I've googled about for a long
: time and couldn't find anything helpful, I've come pretty close
: but I feel like I don't have a completely solid understanding of
: how bind interacts with various windows. here's what I have so
: far. The problem seems to be when the mouse jumps into the red
: area during fast movement. How should I deal with the focus
: stealing of the new window?

I'm not seeing what is wrong. On my system with Tcl 8.6.1 your script
works, presumably, as you intended. Dragging the corner of the
embedded canvas around resizes it within the outer canvas.

You might, however, consider making one change to your script, and that
is this:

--- tt 2014-02-11 23:26:09.325596201 -0500
+++ tt2 2014-02-11 23:24:58.278220922 -0500
@@ -25,7 +25,7 @@
}
}

-bind . <B1-Motion> {
+bind .c.test <B1-Motion> {

global windowid; global xcoord; global ycoord; global pressed

@@ -38,7 +38,7 @@
} else {puts "motion called"}
}

-bind . <ButtonRelease-1> {
+bind .c.test <ButtonRelease-1> {

puts "button not pressed anymore"
set pressed 0

When dealing with motion events, I've found that things work better if
the button down, button motion, and button release bindings are all on
the same window. You may have been having troubles due to having bound
motion and release to "." while binding button down to ".c.test".

bsall...@yahoo.com

unread,
Feb 13, 2014, 5:43:05 PM2/13/14
to
....................................

Just curious as I always like to learn new tcl/tk capabilities.

Does this mean I could use ttk::sizegrip for any widget and have a grip to resize just that widget. I see from man ttk::sizegrip can be used with packed widgets.

If the widget with ttk::sizegrip is packed with other widgets in a frame would using the grip to resize a widget would this be done by making the size of the other widgets in the frame smaller?

Does this type of resize stop when the size of the ttk::sizegrip widget has taken up all of the space in a frame or canvas, or is the top level window increased if there is no more space int the frame or canvas and the grip is still being used to increase the size?

This may be a stupid question, but can the grip be used to make the widget smaller.

Rich

unread,
Feb 13, 2014, 6:23:20 PM2/13/14
to
bsall...@yahoo.com wrote:
The ttk::sizegrip resizes only the toplevel window that it is a part
of. What effect the resize of the toplevel has upon the widgets that
are inside the toplevel is dependent upon the options you use when
packing/gridding/placing them into their respective containers within
the toplevel. It (sizegrip) will make the toplevel smaller as well as
larger, within the constraints set via. wm for the "resizable",
"minsize", and "maxsize" options on the toplevel.


bsall...@yahoo.com

unread,
Feb 14, 2014, 8:15:29 PM2/14/14
to
..................................................
I never use ttk::sizegrip and since I am able to resize the top level window since resizable is the default of wm.

This is why I thought that using ttk::sizegrip would provide the ability to increase the size of specific individual widget item. I am familiar how resizing works with the resize of a top level window.

If the ability to resize the top level window is already available, why would anyone use ttk::sizegrip. Is there special cases where ttk::sizegrip provides something other then the normal ability to be able to resize windows?

Could you use ttk::sizegrip with wm overrideredirect so that you could resize a window that is not handled by the window manager?

Rich

unread,
Feb 15, 2014, 12:27:57 AM2/15/14
to
bsall...@yahoo.com wrote:
Yes, it appears that it is simply an alternative to what the window
manager already provides.

: If the ability to resize the top level window is already available, why
: would anyone use ttk::sizegrip. Is there special cases where
: ttk::sizegrip provides something other then the normal ability to be able
: to resize windows?

I suspect that its only reason for existing is because several other
windowing libraries provide a similar grip in the lower right corner.
So it allows a Tk program to look more "native" in some respects. But
it is wholly duplicative to the controls the window manager provides.

: Could you use ttk::sizegrip with wm overrideredirect so that you could
: resize a window that is not handled by the window manager?

I do not know, never tested it on an overrideredirect window. Why
don't you test one and report back?

bsall...@yahoo.com

unread,
Feb 15, 2014, 2:30:39 AM2/15/14
to
.....................................
Just tried it and it does not work.

You get an error regarding duplication of the same .name for a window.
Looks like it is actually creating a window.



Rich

unread,
Feb 15, 2014, 11:09:36 AM2/15/14
to
bsall...@yahoo.com wrote:
Interesting. It works just fine here under Linux/X11:

#!/usr/bin/wish

wm overrideredirect . true

frame .f -borderwidth 2 -relief solid -width 75 -height 75
ttk::sizegrip .sg

grid .f -sticky news
grid x .sg -sticky news
grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1

This pops up a borderless, frameless window, and the sizegrip will
expand/shrink it as much as one wishes.

bsall...@yahoo.com

unread,
Feb 16, 2014, 1:14:41 PM2/16/14
to
Looked at the documentation and see the grip is like a sub widget being added to another widget and you need a unique name. I used it with a pack and it worked. I mainly use pack but have a small program that uses grid.

With overrideredirect the window was able to move the window with the grip. Did not expand or string since it was tested on a case with expand not being true.

Interesting to know but do not see much value now. Did not like the appearance of the grip.
Interesting that in writing a response I see the text widget has a grip.

bsall...@yahoo.com

unread,
Feb 16, 2014, 1:22:21 PM2/16/14
to
To: Rich

With overrideredirect the window was able to move the window with the grip. Did not expand or string since it was tested on a case with expand not being true.
....................................
Should be
With the grip on a overrideredirect window I was able to move the window. The window did not expand since my test was on code with expand set to false. I was surprised that I could move the window.

ssh...@ucsc.edu

unread,
Feb 25, 2014, 7:14:18 PM2/25/14
to
alright I've come up with a pretty reasonable solution and I'll post it in case anyone needs a size grip for a widget. here's the complete example. Now I only have one problem: the cursor changes back to left_ptr when dragging it

set pressed 0

# testing canvas + scrollbars
tk::canvas .c -scrollregion "0 0 1000 1000" -yscrollcommand ".v set" -xscrollcommand ".h set" -bg blue -highlightthickness 0
ttk::scrollbar .h -orient horizontal -command ".c xview"
ttk::scrollbar .v -orient vertical -command ".c yview"
grid .c -sticky nwes -column 0 -row 0
grid .h -row 1 -column 0 -sticky ew
grid .v -row 0 -column 1 -sticky ns
grid columnconfigure . 0 -weight 1
grid rowconfigure . 0 -weight 1



#create frame and window for "mega" widget
ttk::frame .c.test -width 200 -height 200
.c create window 50 50 -anchor nw -window .c.test

#create ruler, velocity, and keyboard canvases
tk::canvas .c.test.rule -scrollregion "0 0 500 50" -highlightthickness 0 -bg red -height 50
tk::canvas .c.test.kb -scrollregion "0 0 50 500" -highlightthickness 0 -bg green -width 50
#tk::canvas .c.test.vel -scrollregion "0 0 5000 50" -highlightthickness 0 -bg purple -height 50

#create buttons
ttk::frame .c.test.buttons -width 50 -height 50
ttk::button .c.test.buttons.editmode -text edt -width 6 -command editmode
ttk::button .c.test.buttons.selectmode -text select -width 6 -command selmode

#create canvas, sizegrip, and scrollbars for editing region (inframe)
ttk::frame .c.test.inframe
#grid propagate .c.test.inframe 0
grid propagate .c.test 0
ttk::scrollbar .c.test.inframe.h -orient horizontal -command ".c.test.inframe.canvas xview"
ttk::scrollbar .c.test.inframe.v -orient vertical -command ".c.test.inframe.canvas yview"
tk::canvas .c.test.inframe.canvas -scrollregion "0 0 500 500" -xscrollcommand ".c.test.inframe.h set" -yscrollcommand ".c.test.inframe.v set" -highlightthickness 0 -bg yellow

# blank frames for offsetting scrollbars with grid, later maybe have these be zoom controls
ttk::frame .c.test.blankh -width [.c.test.inframe.v cget -width] -height 50
ttk::frame .c.test.blankv -height [.c.test.inframe.h cget -width] -width 50

tk::canvas .c.test.inframe.sz -scrollregion "0 0 [.c.test.inframe.h cget -width] [.c.test.inframe.v cget -width]" -highlightthickness 0 -bg purple -width [.c.test.inframe.h cget -width] -height [.c.test.inframe.v cget -width] -cursor bottom_right_corner


# grid everything todo: change sizegrip line to scale right
.c.test.inframe.sz create line 2 10 10 2 -fill white
grid .c.test.rule -column 1 -row 0 -sticky we
grid .c.test.kb -column 0 -row 1 -sticky ns
#grid .c.test.vel -column 1 -row 2 -sticky w
grid .c.test.buttons -column 0 -row 0 -sticky nsew
grid .c.test.buttons.editmode -column 0 -row 0 -sticky nsew
grid .c.test.buttons.selectmode -column 0 -row 1 -sticky nsew
grid propagate .c.test.buttons 0
grid columnconfigure .c.test.buttons 0 -weight 1
grid rowconfigure .c.test.buttons 0 -weight 0
grid rowconfigure .c.test.buttons 1 -weight 0
grid .c.test.blankh -column 2 -row 0 -sticky ne
grid .c.test.blankv -column 0 -row 2 -sticky sw

# inframe stuff
grid .c.test.inframe -column 1 -row 1 -sticky nwes -columnspan 2 -rowspan 2
grid .c.test.inframe.canvas -column 0 -row 0 -sticky nwes
grid rowconfigure .c.test.inframe 0 -weight 1
grid columnconfigure .c.test.inframe 0 -weight 1

grid .c.test.inframe.v -column 1 -row 0 -sticky ns
grid .c.test.inframe.h -column 0 -row 1 -sticky ew
grid .c.test.inframe.sz -column 1 -row 1 -sticky se


grid rowconfigure .c.test 1 -weight 1
grid rowconfigure .c.test 0 -weight 0
grid columnconfigure .c.test 1 -weight 1
grid columnconfigure .c.test 0 -weight 0

proc selmode {} {
.c.test.inframe.canvas configure -cursor hand1
}

selmode

proc destroyall {} {
foreach w [winfo children .] {
destroy $w
}
}

proc editmode {} {
.c.test.inframe.canvas configure -cursor pencil
}

bind .c.test.inframe.sz <ButtonPress-1> {
global prespos

set prespos [list [expr [.c.test cget -width] - %X] [expr [.c.test cget -height] - %Y]]
puts "pressed"
grab set .c.test.inframe.sz
}

bind .c.test.inframe.sz <B1-Motion> {

global prespos
.c.test configure -width [expr %X + [lindex $prespos 0]] -height [expr %Y + [lindex $prespos 1]]

}

bind .c.test.inframe.sz <Leave> {

puts "left"
}

bind .c.test.inframe.sz <Enter> {

puts "entered"
}

bind .c.test.inframe.sz <ButtonRelease-1> {
grab release .c.test.inframe.sz
}

0 new messages