Hello, World! Simple Widgets Binding Events More Widgets Scrollbars Menus Canvas Make things look Beautiful More Information

We are moving to this wiki

Combining some More Widgets

Somewhat larger UIs will use sets of grouped widgets. We will give a combined packing and gridding example, after which we will fit it all a bit nicer in resized windows.

We have already seen you can put widgets in the root window. Tk provides one specific widget for grouping: the TkFrame. It behaves the same as a root, though it has a few options that differ. Here is an example:

root = TkRoot.new() { title "More Widgets" }
frame = TkFrame.new(root).pack("side"=>"right")
buttons = TkFrame.new(frame).pack("side"=>"bottom")
load = TkButton.new(buttons) { text "Load" }
save = TkButton.new(buttons) { text "Save" }
TkGrid.configure(load, save)
There really is not much to say about this.
Well, we could have done this with only one frame. Let us continue the example and see what happens.
display = TkFrame.new(root).pack("side"=>"left")
editor = TkText.new(display).pack()  # top
status = TkLabel.new(display) { text "launching..." }
status.pack("side"=>"bottom", "anchor"=>"w")
list = TkListbox.new(frame).pack()
list.insert("end", "/some/file")
list.insert("end", "/etc/hosts")
Still nothing special happened, but you should get an idea where we are going with the application, right? What a TkListbox is, I hear you ask? It displays a list and we will come back to it when we discuss scrollbars.

Fitting the widgets better

Even before you resize the window, we think the list and buttons are not positioned nicely. So let's add
list.pack("fill"=>"y")
Yes, simply add it at the end of the script (well, before Tk.mainloop, of course). Calling pack is configuring the packing procedure, as well as calling it again. This can be useful to add buttons on the fly, in response to what a user does.

Surprise, that does not work! Why not? Because list never got any more space to display itself in. Which widget might give it space? Right, the frame that packs it.

frame.pack("fill"=>"y")
Something happened, but not what we intended! The frame filled vertically, all right, but the list did not. That is because the frame gives the list space in the tophalf of the screen, according to its height. The only direction in which the list can fill is horizontally! We will solve this below.

Enlarging the window

But first, enlarge the window in both directions. Yuck, even more space in between the widgets. The list does not even fill horizontally, but that is because the frame it is in suffers from the same problem: it can only fill vertically (which it does). We need to tell the widgets to expand, when given that possibility: The packer will distribute extra space that is available, among the widgets that wish to expand. If there are none, it is padded in between the (top vs bottom or left vs right) widgets.
display.pack("fill"=>"both", "expand"=>true)
editor.pack("fill"=>"both", "expand"=>true)
list.pack("expand"=>true)
We want editor to take whatever space possible. Broad buttons or a high status label are useless. So editor needs to fill whatever space assigned, in "both" directions and it needs to expand to grab that extra space.

The same holds for display, the frame that contains editor and for list that needs to expand vertically.

Anything unequal to zero will tell Tk to actually expand. We think true is a nice Ruby construct to use here.

Typical usage

You will typically find that your TkFrames fill in at least one direction and need to expand as well when they fill in both directions. The same holds for TkListboxes, and central widgets like a TkCanvas or a TkText.

On the other hand, a TkMessage, though multiline, will almost never need to fill and expand.

Shrinking the Window

When you shrink the window beyond its original size (vertically), you will miss the status label. This is due to the packing order. Within display, editor is packed first and then status. You could switch the statements in the construction, but you can also add:
status.pack("before"=>editor)
All stuff with the list and buttons is already in what we think is the right order.

This who-first may seem irrelevant, but is extremely important when you port your applications to smaller (or bigger) screens. The author owns an iPAQ and is very happy with these orderings. A window manager like ion has other ideas of sizes assigned to windows than Tk and usually wins.


Hello, World! Simple Widgets Binding Events More Widgets Scrollbars Menus Canvas Make things look Beautiful More Information

Kero