Reputation: 29
I am new in tcl\tk and I am developing a UI using it. The UI window has a frame that has dynamic number of labels and text widgets filled according to the number of columns in a table. There is an entry widget for each column, data typed in it by user populates each column in the table.
However the problem I am facing is that , I cannot find a way to make the size and position of the widgets inside the frame in the window adjust themselves according to the size of the window. That is if the user enlarges the window by dragging and enlarging its size the widgets inside the window should also increase in size and adjust their positions according to the window size. Vice versa if the window size id decreased. Something like bootstrap in HTML, CSS. Can anyone please give me any idea?? Any help is greatly appreciated. Thanks!
Upvotes: 0
Views: 1678
Reputation: 5723
You need to read the documentation on the grid and pack commands.
With pack
, the -fill
and -expand
options will help you adjust how the
widget reacts to resizing.
Examples:
pack .widget -fill both -expand true
pack .widget -fill x -expand true -anchor s
With grid
, the -sticky
option and columnconfigure
and rowconfigure
sub-commands will be useful to you.
Examples:
grid .widget -sticky ew
grid columnconfigure . 0 -weight 1
In some cases there may be special actions you will need to take upon a resize. In this case, the bind command will be useful. You can bind to a <Configure>
event and adjust widget sizes or take other actions as necessary.
Edit:
The grid columnconfigure
applies to a column of a containing frame. So you don't have to run it for each widget. In the example above, .widget
is contained in the .
frame and the .
frame's column is configured.
# in this example, the entry fields will adjust their width when
# the window is resized.
package require Tk
grid columnconfigure . 1 -weight 1
foreach {val} {1 2 3 4 5 6 7} {
ttk::label .lab$val -text "Label $val:"
ttk::entry .entry$val -textvariable mydata($val)
grid .lab$val .entry$val -in . -sticky w
# change the configuration for .entry$val only...
grid configure .entry$val -sticky ew
}
proc doresize { win } {
puts "Win $win now has width: [winfo width $win]"
}
bind . <Configure> [list ::doresize %W]
Note that with this example, the bind
also applies to all of the children of .
as .
is a top-level window. If you are only interested in changes to .
, you can change the resize procedure:
proc doresize { win } {
if { $win eq "." } {
puts "Win $win now has width: [winfo width $win]"
}
}
If the bind
is applied to a frame or widget that is not a top-level window, the events are only received for that frame or widget.
Also note that you will receive all the events. Further changes can be made to check for changes to the width:
set vars(last.width) 0
proc doresize { win } {
variable vars
if { $win eq "." } {
set newwidth [winfo width $win]
if { $newwidth != $vars(last.width) } {
puts "Win $win now has width: [winfo width $win]"
if { $vars(last.width) != 0 } {
# this is not the first time, as last.width is not zero
# do something due to window resize.
}
set vars(last.width) $newwidth
}
}
}
Upvotes: 0