1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
|
.. currentmodule:: gi.repository
Layout Containers
=================
While many GUI toolkits require you to precisely place widgets in a window,
using absolute positioning, GTK uses a different approach.
Rather than specifying the position and size of each widget in the window,
you can arrange your widgets in rows, columns, and/or tables.
The size of your window can be determined automatically, based on the sizes
of the widgets it contains.
And the sizes of the widgets are, in turn, determined by the amount of text
they contain, or the minimum and maximum sizes that you specify, and/or how
you have requested that the available space should be shared between sets of
widgets. You can perfect your layout by specifying padding distance and
centering values for each of your widgets. GTK then uses all this information
to resize and reposition everything sensibly and smoothly when the user
manipulates the window.
GTK widgets can parent other widgets hierarchically, and the way those widgets
are displayed depend on the :class:`Gtk.LayoutManager` set in the
:attr:`Gtk.Widget.props.layout_manager` property. For ease of use, GTK provides
"pre made" containers that have default layout managers for different needs.
Most of these containers implement the :class:`Gtk.Orientable` interface, it
allows to set the widget orientation using
:attr:`Gtk.Orientable.props.orientation`, you can either set
:attr:`Gtk.Orientation.HORIZONTAL` or :attr:`Gtk.Orientation.VERTICAL`.
Some containers / layout managers like :class:`Gtk.Box` allow you to influence
the allocation of a child using the :attr:`Gtk.Widget.props.halign`,
:attr:`Gtk.Widget.props.valign`, :attr:`Gtk.Widget.props.hexpand` and
:attr:`Gtk.Widget.props.vexpand` properties.
The main container widgets are:
* :class:`Gtk.Box`
* :class:`Gtk.CenterBox`
* :class:`Gtk.HeaderBar`
* :class:`Gtk.Grid`
* :class:`Gtk.ListBox`
* :class:`Gtk.FlowBox`
* :class:`Gtk.Stack`
* :class:`Gtk.Notebook`
We are looking into each one in the following sections.
Boxes
-----
Boxes are invisible containers into which we can pack our widgets.
When packing widgets into a horizontal box, the objects are inserted
horizontally from left to right or right to left depending on whether
:meth:`Gtk.Box.prepend` or :meth:`Gtk.Box.append` is used.
You can also use the :meth:`Gtk.Box.insert_child_after` or
:meth:`Gtk.Box.reorder_child_after` methods to insert a widget on a specific
position.
In a vertical box, widgets are packed from top to bottom or vice versa.
You may use any combination of boxes inside or beside other boxes to create
the desired effect.
Example
^^^^^^^
Let's take a look at a slightly modified version of
the :ref:`extended-example` with two buttons.
.. image:: images/layout_box.png
.. literalinclude:: examples/layout_box.py
:linenos:
First, we create a horizontally orientated box container where 6 pixels are
placed between children. This box becomes the child of the top-level window.
.. literalinclude:: examples/layout_box.py
:lines: 11-12
Subsequently, we add two different buttons to the box container.
.. literalinclude:: examples/layout_box.py
:lines: 14-21
CenterBox
---------
:class:`Gtk.CenterBox` arranges three children in a row or a column depending on
its orientation, keeping the middle child centered as well as possible.
To add children you use :meth:`Gtk.CenterBox.set_start_widget`,
:meth:`Gtk.CenterBox.set_center_widget`, and :meth:`Gtk.CenterBox.set_end_widget`.
Example
^^^^^^^
.. image:: images/layout_center.png
.. literalinclude:: examples/layout_center.py
:linenos:
HeaderBar
---------
A :class:`Gtk.HeaderBar` is similar to a horizontal :class:`Gtk.CenterBox`, it
allows to place children at the start or the end. In addition, it allows a title
to be displayed. The title will be centered with respect to the width of the box,
even if the children at either side take up different amounts of space.
:class:`Gtk.HeaderBar` is designed to be used as a window titlebar.
This means that it can show typical window frame controls, such as minimize,
maximize and close buttons, or the window icon.
It is also draggable, meaning that you can move the parent window from it.
You can use the :meth:`Gtk.Window.set_titlebar` method to set it as so.
To add children you use :meth:`Gtk.HeaderBar.pack_start`,
:meth:`Gtk.HeaderBar.pack_end`, and :meth:`Gtk.HeaderBar.set_title_widget` for
the center one. By default if no ``title_widget`` is set
it will have a label with the window's :attr:`Gtk.Window.props.title`.
Example
^^^^^^^
.. image:: images/layout_headerbar.png
.. literalinclude:: examples/layout_headerbar.py
:linenos:
Grid
----
:class:`Gtk.Grid` is a container which arranges its child widgets in rows and
columns, but you do not need to specify the dimensions in the constructor.
Children are added using :meth:`Gtk.Grid.attach`. They can span multiple rows or
columns. The :meth:`Gtk.Grid.attach` method takes five parameters:
1. The ``child`` parameter is the :class:`Gtk.Widget` to add.
2. ``left`` is the column number to attach the left side of ``child`` to.
3. ``top`` indicates the row number to attach the top side of ``child`` to.
4. ``width`` and ``height`` indicate the number of columns that the ``child``
will span, and the number of rows that the ``child`` will span, respectively.
It is also possible to add a child next to an existing child, using
:meth:`Gtk.Grid.attach_next_to`, which also takes five parameters:
1. ``child`` is the :class:`Gtk.Widget` to add, as above.
2. ``sibling`` is an existing child widget of ``self`` (a :class:`Gtk.Grid` instance)
or ``None``. The ``child`` widget will be placed next to ``sibling``, or
if ``sibling`` is ``None``, at the beginning or end of the grid.
3. ``side`` is a :class:`Gtk.PositionType` indicating the side of
``sibling`` that ``child`` is positioned next to.
4. ``width`` and ``height`` indicate the number of columns and rows
the ``child`` widget will span, respectively.
Example
^^^^^^^
.. image:: images/layout_grid.png
.. literalinclude:: examples/layout_grid.py
:linenos:
ListBox
-------
A :class:`Gtk.ListBox` is a vertical container that contains :class:`Gtk.ListBoxRow`
children. These rows can be dynamically sorted and filtered, and headers can be
added dynamically depending on the row content. It also allows keyboard and
mouse navigation and selection like a typical list.
Although a :class:`Gtk.ListBox` must have only :class:`Gtk.ListBoxRow` children,
you can add any kind of widget to it via :meth:`Gtk.ListBox.append` or
:meth:`Gtk.ListBox.insert` and a :class:`Gtk.ListBoxRow` widget will
automatically be inserted between the list and the widget.
:class:`Gtk.ListBox` allows activating and selecting its children.
Selection can be configured with :attr:`Gtk.ListBox.props.selection_mode`,
selection modes are :attr:`Gtk.SelectionMode.NONE` (not selection at all),
:attr:`Gtk.SelectionMode.SINGLE` (one or none elements can be selected),
:attr:`Gtk.SelectionMode.BROWSE` (user can't deselect a currently selected
element except by selecting another element) and
:attr:`Gtk.SelectionMode.MULTIPLE` (any number of elements may be selected).
It will emit the :func:`row-activated <Gtk.ListBox.signals.row_activated>`
signal when a row is activated in any form, and
:func:`row-selected <Gtk.ListBox.signals.row_selected>` when a row is selected.
Example
^^^^^^^
.. image:: images/layout_listbox.png
.. literalinclude:: examples/layout_listbox.py
:linenos:
FlowBox
-------
A :class:`Gtk.FlowBox` is a container that positions child widgets in sequence
according to its orientation.
For instance, with the horizontal orientation, the widgets will be arranged
from left to right, starting a new row under the previous row when necessary.
Reducing the width in this case will require more rows, so a larger height
will be requested.
Likewise, with the vertical orientation, the widgets will be arranged from top
to bottom, starting a new column to the right when necessary. Reducing the
height will require more columns, so a larger width will be requested.
:class:`Gtk.FlowBox` behaves similar to :class:`Gtk.ListBox`, we could say that
is its "grid" counterpart. Just like :class:`Gtk.ListBox`, the children of a
:class:`Gtk.FlowBox` can be dynamically sorted and filtered, and also activated
and selected.
Although a :class:`Gtk.FlowBox` must have only :class:`Gtk.FlowBoxChild`
children, you can add any kind of widget to it via
:meth:`Gtk.FlowBox.append` or :meth:`Gtk.FlowBox.insert`, and a
:class:`Gtk.FlowBoxChild` widget will automatically be inserted between the box
and the widget.
Example
^^^^^^^
.. image:: images/layout_flowbox.png
.. literalinclude:: examples/layout_flowbox.py
:linenos:
Stack and StackSwitcher
-----------------------
A :class:`Gtk.Stack` is a container which only shows one of its children at a
time. In contrast to :class:`Gtk.Notebook`, :class:`Gtk.Stack` does not provide
a means for users to change the visible child. Instead, the
:class:`Gtk.StackSwitcher` widget can be used with :class:`Gtk.Stack` to
provide this functionality.
Transitions between pages can be animated as slides or fades. This can be
controlled with :attr:`Gtk.Stack.props.transition_type`. These animations
respect the ``gtk-enable-animations`` setting.
Transition speed can be adjusted with :attr:`Gtk.Stack.props.transition_duration`.
The :class:`Gtk.StackSwitcher` widget acts as a controller for a
:class:`Gtk.Stack`; it shows a row of buttons to switch between the various
pages of the associated stack widget.
:class:`Gtk.Stack` uses the auxiliary :class:`Gtk.StackPage` object.
:class:`Gtk.Stack` will return a :class:`Gtk.StackPage` every time you add a new
children, either with :meth:`Gtk.Stack.add_child`, :meth:`Gtk.Stack.add_named`
or :meth:`Gtk.Stack.add_titled`.
:class:`Gtk.StackPage` holds important properties for the stack's children, like
the name, the title to display, or if the page needs attention, then this data
can be used for example by :class:`Gtk.StackSwitcher`.
It is possible to associate multiple :class:`Gtk.StackSwitcher` widgets with
the same :class:`Gtk.Stack` widget.
Example
^^^^^^^
.. image:: images/layout_stack.png
.. literalinclude:: examples/layout_stack.py
:linenos:
Notebook
--------
The :class:`Gtk.Notebook` is a container whose children are pages switched
between using tabs.
There are many configuration options for GtkNotebook. Among other things, you
can choose on which edge the tabs appear (see :meth:`Gtk.Notebook.set_tab_pos`),
whether, if there are too many tabs to fit the notebook should be made bigger or
scrolling arrows added (see :meth:`Gtk.Notebook.set_scrollable`), and whether
there will be a popup menu allowing the users to switch pages (see
:meth:`Gtk.Notebook.popup_enable`, :meth:`Gtk.Notebook.popup_disable`).
You can add children with :meth:`Gtk.Notebook.append_page`, it takes two widgets,
the first is the widget to show as a page, and the second is the widget to show
as the tab content.
Example
^^^^^^^
.. image:: images/layout_notebook.png
.. literalinclude:: examples/layout_notebook.py
:linenos:
|