Flerobjektsbehållare

Multiple-item container widgets have other methods than set_child() and unset_child(). Different containers can have different methods for adding and removing child widgets. For instance, Gtk::Box has append() and remove() as well as other methods. The remove() method for multiple-item containers takes an argument, specifying which widget to remove.

Packning

Du har troligen upptäckt att gtkmm-fönster verkar ”elastiska” - de kan vanligen sträckas ut på många olika sätt. Det här är på grund av systemet för komponentpackning.

Många verktygslådor för grafiska användargränssnitt kräver att du precist placerar komponenter i ett fönster med absolut positionering, ofta med en visuell redigerare. Detta leder till flera problem:

  • Komponenterna arrangerar inte om sig själva när fönstrets storlek ändras. Vissa komponenter döljs när fönstret görs mindre, och mycket onödigt utrymme uppstår när fönstret görs större.

  • Det är omöjligt att förutse mängden utrymme som krävs för text efter att den har översatts till andra språk, eller visas med ett annat typsnitt. På Unix är det också omöjligt att förutse effekterna av varje tema och fönsterhanterare.

  • Att ändra layouten för ett fönster ”i farten”, exempelvis för att få några extra komponenter att visas, är komplext. Det kräver tröttsam omräkning av varje komponents position.

gtkmm uses the packing system to solve these problems. Rather than specifying the position and size of each widget in the window, you can arrange your widgets in rows, columns, and/or grids. gtkmm can size your window 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 margins and centering values for each of your widgets. gtkmm then uses all this information to resize and reposition everything sensibly and smoothly when the user manipulates the window.

gtkmm arrangerar komponenter hierarkiskt med behållare. En behållarkomponent innehåller andra komponenter. De flesta gtkmm-komponenter är behållare. Fönster, anteckningsblocksflikar och knappar är alla behållarkomponenter. Det finns två sorters behållare: behållare med en underordnad och de med flera underordnade. De flesta behållarkomponenter i gtkmm är behållare med en underordnad, inklusive Gtk::Window.

Det stämmer: ett Window kan innehålla högst en komponent. Men hur kan vi då använda ett fönster för något användbart? Genom att placera en flerobjektsbehållare i fönstret. De mest användbara behållarkomponenterna är Gtk::Grid och Gtk::Box.

  • Gtk::Grid arrangerar sina underordnade komponenter i rader och kolumner. Använd attach() och attach_next_to() för att infoga underordnade komponenter.

  • Gtk::Box arrangerar sina underordnade komponenter vertikalt eller horisontellt. Använd append() för att infoga underordnade komponenter.

Det finns flera andra behållare som vi också kommer diskutera.

If you've never used a packing toolkit before, it can take some getting used to. You'll probably find, however, that you don't need to rely on visual form editors quite as much as you might with other toolkits.

Ett förbättrat Hej världen

Låt oss ta en titt på ett något förbättrat helloworld som visar vad vi lärt oss.

Hej världen 2

Källkod

After building and running this program, try resizing the window to see the behavior. Also, try playing with set_expand(), set_hexpand(), set_vexpand(), set_halign() and set_valign() while reading the Boxes section.

Boxes

Most packing uses boxes as in the above example. These 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. In a vertical box, widgets are packed from top to bottom. You may use any combination of boxes inside or beside other boxes to create the desired effect.

Lägga till komponenter

Packningsalternativ per underordnad

Metoden append() placerar komponenter inuti dessa behållare. Den kommer starta uppifrån och arbeta sig nedåt i en Box med vertikal orientering, eller packa från vänster till höger i en Box med horisontell orientering. Om det är opraktiskt att lägga till komponenter i denna ordning kan du använda insert_child_after() eller insert_child_at_start(). Vi kommer använda append() i våra exempel.

There are several options governing how widgets are to be packed, and this can be confusing at first. You can modify the packing by using set_expand(), set_hexpand(), set_vexpand(), set_halign(), set_valign() and/or set_margin() on the child widgets. If you have difficulties, then it is sometimes a good idea to play with the glade GUI designer to see what is possible. You might even decide to use the Gtk::Builder API to load your GUI at runtime.

Det finns i grunden fem olika stilar som kan ses i denna bild:

Boxpackning 1

Each line contains one horizontal Box with several buttons. Each of the buttons on a line is packed into the Box with the same arguments to the set_hexpand(), set_halign(), set_margin_start() and set_margin_end() methods.

Referens

Per-container packing options

Here's the constructor for the Box widget, and methods that set per-container packing options:

Gtk::Box(Gtk::Orientation orientation = Gtk::Orientation::HORIZONTAL, int spacing = 0);
void set_orientation(Gtk::Orientation orientation);
void set_spacing(int spacing);
void set_homogeneous(bool homogeneous = true);
Passing true to set_homogeneous() will cause all of the contained widgets to be the same size. spacing is a (minimum) number of pixels to leave between each widget.

What's the difference between spacing (set when the box is created) and margins (set separately for each child widget)? Spacing is added between objects, and margins are added on one or more sides of a widget. The following figure should make it clearer. The shown margins are the left and right margins of each button in the row.

Boxpackning 2

Gtk::Application och kommandoradsflaggor

Följande exempelprogram kräver en kommandoradsflagga. Källkoden visar två sätt att hantera kommandoradsflaggor i kombination med Gtk::Application.

  • Hantera flaggorna i main() och dölj dem från Gtk::Application genom att ställa in argc = 1 i anropet till Gtk::Application::run().

  • Ge alla kommandoradsflaggor till Gtk::Application::run() och lägg till flaggan Gio::Application::Flags::HANDLES_COMMAND_LINE till Gtk::Application::create(). Anslut en signalhanterare till signalen command_line, och hantera kommandoradsflaggorna i signalhanteraren.

    You must set the optional parameter after = false in the call to signal_command_line().connect(), because your signal handler must be called before the default signal handler. You must also call Gio::Application::activate() in the signal handler, unless you want your application to exit without showing its main window. (Gio::Application is a base class of Gtk::Application.)

Exempel

Here is the source code for the example that produced the screenshots above. When you run this example, provide a number between 1 and 3 as a command-line option, to see different packing options in use.

Källkod

Grid

Ett Grid organiserar dynamiskt underordnade komponenter i rader och kolumner. Dimensionerna på rutnätet behöver inte anges i konstruktorn.

Underordnade komponenter kan spänna över flera rader eller kolumner med attach(), eller läggas intill en befintlig komponent i rutnätet med attach_next_to(). Individuella rader och kolumner i rutnätet kan ställas in att ha enhetlig höjd eller bredd med set_row_homogeneous() och set_column_homogeneous().

You can set the margin and expand properties of the child Widgets to control their spacing and their behavior when the Grid is resized.

Referens

Exempel

Detta exempel skapar ett fönster med tre knappar i ett rutnät. De första två knapparna är i den övre raden, från vänster till höger. En tredje knapp infogas under den första knappen i en ny lägre rad, och spänner över två kolumner.

Grid

Källkod

Notebook

A Notebook has a set of stacked pages, each of which contains widgets. Labelled tabs allow the user to select the pages. Notebooks allow several sets of widgets to be placed in a small space, by only showing one page at a time. For instance, they are often used in preferences dialogs.

Use the append_page(), prepend_page() and insert_page() methods to add tabbed pages to the Notebook, supplying the child widget and the name for the tab.

Använd metoden get_current_page() för att avgöra vilken sida som är synlig för tillfället. Detta returnerar sidnumret, och att sedan anropa get_nth_page() med det numret kommer ge dig en pekare till den faktiska underordnade komponenten.

To programmatically change the selected page, use the set_current_page() method.

Referens

Exempel

Notebook

Källkod

Assistant

Gtk::Assistant är föråldrad sedan gtkmm 4.10. Det finns ingen ersättning i gtkmm. libadwaita (ett C-bibliotek) har ersättningsdelar (som AdwCarousel). I vissa fall kan en Gtk::Notebook vara en acceptabel ersättning.

An Assistant splits a complex operation into steps. Each step is a page, containing a header, a child widget and an action area. The Assistant's action area has navigation buttons which update automatically depending on the type of the page, set with set_page_type().

Use the append_page(), prepend_page and insert_page() methods to add pages to the Assistant, supplying the child widget for each page.

To determine the currently-visible page, use the get_current_page() method, and pass the result to get_nth_page(), which returns a pointer to the actual widget. To programmatically change the current page, use the set_current_page() method.

Använd metoden set_page_title() för att ställa in titeln för en sida.

To add widgets to the action area, use the add_action_widget() method. They will be packed alongside the default buttons. Use the remove_action_widget() method to remove widgets.

Referens

Exempel

Assistant

Källkod

Andra flerobjektsbehållare

Det finns andra flerobjektsbehållare. Se referensdokumentationen för en fullständig lista. Här är länkar till några exempelprogram som visar behållare som inte nämns någon annanstans i denna handledning.

Källkod, ActionBar

Källkod, FlowBox