In this chapter, we briefly introduce the concept of packing, which is the primary mechanism for window layout in GTK--. We also present a brief catalog of the most commonly used GTK-- widgets.
If you've played with GTK applications, you've probably noticed that GTK windows seem "elastic"; they can usually be stretched in many different ways. This ability is due to the widget packing system, a concept borrowed (with several other concepts) from TK.
Most GUI toolkits allow you to place widgets on a window in arbitrary positions. In Delphi or Visual C++, for example, you place a button on a form by specifying its coordinates relative to the upper left-hand corner of the window. While this is easy to understand, and gives you quite a bit of flexibility, it also has some disadvantages:
GTK uses the packing system to solve these problems. Rather than making you specify the position and size of each widget in the window, you can instead tell GTK to arrange your widgets in rows, columns, and/or tables. GTK can size your window automatically, based on the sizes of the widgets it contains. You can further tune your layout by specifying padding distance, centering values, and minimum and maximum sizes for each of your widgets, among other things. GTK then uses all this information to do the right thing when the user resizes a window.
GTK arranges windows hierarchically, using containers. A
container is a widget which contains other widgets. Most GTK widgets
are containers; windows, borders, notebook tabs, and buttons are all
container widgets. There are two flavours of containers in GTK:
single-child containers, which are all descendants of Gtk::Bin
,
and multiple-child containers, which are descendants of
Gtk::Container
. Most widgets in GTK are descendants of
Gtk::Bin
, including Gtk::Window
.
Yes, that's correct: a GTK window can contain at most one widget. How, then, can we use a window for anything useful? By placing a multiple-child container in the window. GTK-- offers several basic multi-child containers:
Gtk::VBox
places its widgets one on top of another.
Gtk::HBox
arranges its widgets side-by-side.
Gtk::Packer
packs its widgets in TK-style.
Gtk::Fixed
allows you to place widgets inside it the
old-fashioned way, using coordinates.
Gtk::Table
arranges its widgets in a grid.There are quite a few other containers in GTK--; see Container Widgets for a complete discussion of them.
If you've never used a packing toolkit before, it can take a bit of getting used to. You'll probably find, however, that you don't need to rely on form-painters with GTK quite as much as you did with other toolkits. For a complete discussion of packing and packing theory, see the section Packing Widgets. For now, we'll just mention a few of the most common packing-related calls, because we'll be using them in our upcoming examples:
Gtk::Box::pack_start()
places a widget near the top for
VBox
es, and near the left for HBox
es.
Gtk::Box::pack_end()
places a widget near the bottom for
VBox
es, and near the right for HBox
es.Essentially, successive calls to pack_start()
will result in your
widgets being "packed in" in a row or column.
The steps for using a GTK-- widget are:
_impl
methods.
Gtk::Container::add()
or Gtk::Box::pack_start()
.
Gtk::Widget::show()
to display the widget.Gtk::Widget::show()
lets GTK-- know that we are done setting the
attributes of the widget, and that it is ready to be displayed. You
can use Gtk::Widget::hide()
to make it disappear again. The order
in which you show the widgets is not important, but we do suggest
that you show the window last; this way, the whole window
will appear with its contents already drawn. Otherwise, the user will
first see a blank window, and then the widgets will begin to appear
in it, which doesn't look quite as nice.
Here is the class hierarchy for GTK-- widgets:
Gtk::Object
+Gtk::Widget
| +Gtk::Misc
| | +Gtk::Label
| | | +Gtk::AccelLabel
| | | `Gtk::TipsQuery
| | +Gtk::Arrow
| | +Gtk::Image
| | `Gtk::Pixmap
| +Gtk::Container
| | +Gtk::Bin
| | | +Gtk::Alignment
| | | +Gtk::Frame
| | | | `Gtk::AspectFrame
| | | +Gtk::Button
| | | | +Gtk::ToggleButton
| | | | | `Gtk::CheckButton
| | | | | `Gtk::RadioButton
| | | | `Gtk::OptionMenu
| | | +Gtk::Item
| | | | +Gtk::MenuItem
| | | | | +Gtk::CheckMenuItem
| | | | | | `Gtk::RadioMenuItem
| | | | | `Gtk::TearoffMenuItem
| | | | +Gtk::ListItem
| | | | `Gtk::TreeItem
| | | +Gtk::Window
| | | | +Gtk::ColorSelectionDialog
| | | | +Gtk::Dialog
| | | | | `Gtk::InputDialog
| | | | +Gtk::DrawWindow
| | | | +Gtk::FileSelection
| | | | +Gtk::FontSelectionDialog
| | | | `Gtk::Plug
| | | +Gtk::EventBox
| | | +Gtk::HandleBox
| | | +Gtk::ScrolledWindow
| | | `Gtk::Viewport
| | +Gtk::Box
| | | +Gtk::ButtonBox
| | | | +Gtk::HButtonBox
| | | | `Gtk::VButtonBox
| | | +Gtk::VBox
| | | | +Gtk::ColorSelection
| | | | `Gtk::GammaCurve
| | | `Gtk::HBox
| | | +Gtk::Combo
| | | `Gtk::Statusbar
| | +Gtk::CList
| | | `Gtk::CTree
| | +Gtk::Fixed
| | +Gtk::Notebook
| | | `Gtk::FontSelection
| | +Gtk::Paned
| | | +Gtk::HPaned
| | | `Gtk::VPaned
| | +Gtk::Layout
| | +Gtk::List
| | +Gtk::MenuShell
| | | +Gtk::MenuBar
| | | `Gtk::Menu
| | +Gtk::Packer
| | +Gtk::Socket
| | +Gtk::Table
| | +Gtk::Toolbar
| | `Gtk::Tree
| +Gtk::Calendar
| +Gtk::DrawingArea
| | `Gtk::Curve
| +Gtk::Editable
| | +Gtk::Entry
| | | `Gtk::SpinButton
| | `Gtk::Text
| +Gtk::Ruler
| | +Gtk::HRuler
| | `Gtk::VRuler
| +Gtk::Range
| | +Gtk::Scale
| | | +Gtk::HScale
| | | `Gtk::VScale
| | `Gtk::Scrollbar
| | +Gtk::HScrollbar
| | `Gtk::VScrollbar
| +Gtk::Separator
| | +Gtk::HSeparator
| | `Gtk::VSeparator
| +Gtk::Preview
| `Gtk::Progress
| `Gtk::ProgressBar
+Gtk::Data
| +Gtk::Adjustment
| `Gtk::Tooltips
`Gtk::ItemFactory
The following widgets do not have an associated window; they
therefore do not receive events. If you want to capture events for
these widgets, you can use a special container called
Gtk::EventBox
, which is described in the section
EventBox.
Gtk::Alignment
Gtk::Arrow
Gtk::Bin
Gtk::Box
Gtk::Image
Gtk::Item
Gtk::Label
Gtk::Pixmap
Gtk::ScrolledWindow
Gtk::Separator
Gtk::Table
Gtk::AspectFrame
Gtk::Frame
Gtk::VBox
Gtk::HBox
Gtk::VSeparator
Gtk::HSeparator
These widgets are mainly used for decoration, so you won't often need to capture events on them.