GTK/ Boxen

Aus Wikibooks

< GTK
Wechseln zu: Navigation, Suche

GTK arbeitet nicht wie manch andere Lösungen mit einer pixelartigen Anordnung von Elementen, die ohne einen speziellen Zusammenhang in ein Fenster geklatscht werden. Stattdessen werden Elemente in Boxen zusammengeschlossen, wodurch eine Sinnanordnung entsteht - diese könnte theoretisch auch für Computer auswertbar sein, würde er den Sinn der Elemente verstehen. Das ist aber ein anderes Thema und soll hier deshalb nicht besprochen werden.

Inhaltsverzeichnis

[Bearbeiten] Das gewaltige Angebot der Boxen

Von diesen Boxen gibt es eine ganze Reihe für die verschiedensten Zwecke. Allen gemein ist, dass sie mehrere Elemente in einer bestimmten Reihenfolge anordnen. Und dann gibt es auch noch Container. Diese können zwar nur ein Element aufnehmen, darunter kann sich dann allerdings eine Box befinden - diese kann wiederum beliebig viele Elemente aufnehmen.

Warum unterscheidet man dies? Es gibt einen Grund: es gibt unter anderem die beiden oft benötigten Boxen GtkHBox und GtkVBox. Sie ordnen ihre Kindelemente horizontal beziehungsweise vertikal an. Fenster sind auch Elemente, die andere Elemente enthalten sollen. Dabei gibt es nur ein Problem: angenommen, ein Fenster ist eine Box. In welcher Richtung sollen die Kindelemente angeordnet werden? Horizontal? Vertikal? Oder vielleicht ganz anders? Da es dem Konzept des sauberen Programmierens widerspricht, entscheidet man sich nicht dafür, zwei Arten von Fenstern einzuführen, sondern dem Programmierer diese Entscheidung zu übergeben. Dieser kann dann seine gewünschte Box in das Fenster packen und seine Elemente darin beliebig anordnen.

Fangen wir also an, uns diese Boxen etwas näher anzuschauen: am Einfachsten zu veranschaulichen sind wohl die bereits erwähnten zwei Boxen. Also schauen wir uns mal beide Alternativen an - wir ordnen jeweils drei Textfelder in einem Fenster an.

[Bearbeiten] Horizontale Anordnung

Horizontale Anordnung von drei Labels.
Horizontale Anordnung von drei Labels.
  1. #include <gtk/gtk.h>
  2.  
  3.  int main(int argc, char *argv[])
  4.  {
  5.      GtkWidget *window, *box;
  6.      
  7.      gtk_init(&argc, &argv);
  8.      
  9.      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  10.      g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
  11.      
  12.      box = gtk_hbox_new(false, 10);
  13.      
  14.      gtk_box_pack_start(GTK_BOX(box), gtk_label_new("Nummer Eins"), false, false, 0);
  15.      gtk_box_pack_start(GTK_BOX(box), gtk_label_new("Nummer Zwei"), false, false, 0);
  16.      gtk_box_pack_start(GTK_BOX(box), gtk_label_new("Nummer Drei"), false, false, 0);
  17.      
  18.      gtk_container_add(GTK_CONTAINER(window), box);
  19.      
  20.      gtk_widget_show_all(window);
  21.      
  22.      gtk_main();
  23.  }
Vertikale Anordnung von drei Labels.
Vertikale Anordnung von drei Labels.

[Bearbeiten] Vertikale Anordnung

  1. #include <gtk/gtk.h>
  2.  
  3.  int main(int argc, char *argv[])
  4.  {
  5.      GtkWidget *window, *box;
  6.      
  7.      gtk_init(&argc, &argv);
  8.      
  9.      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  10.      g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
  11.      
  12.      box = gtk_vbox_new(false, 10);
  13.      
  14.      gtk_box_pack_start(GTK_BOX(box), gtk_label_new("Nummer Eins"), false, false, 0);
  15.      gtk_box_pack_start(GTK_BOX(box), gtk_label_new("Nummer Zwei"), false, false, 0);
  16.      gtk_box_pack_start(GTK_BOX(box), gtk_label_new("Nummer Drei"), false, false, 0);
  17.      
  18.      gtk_container_add(GTK_CONTAINER(window), box);
  19.      
  20.      gtk_widget_show_all(window);
  21.      
  22.      gtk_main();
  23.  }

Man sieht, der Quelltext ist fast identisch - so auch die Arbeit mit den verschiedenen Typen von Boxen. Nur eines unterscheidet sich: die Zeile zum Erzeugen der Box. Beim ersten Mal wird eine horizontale Box erzeugt, die ihre Elemente von links nach rechts anordnet, beim zweiten Mal wird eine Box erzeugt, die ihre Elemente untereinander anordnet.

[Bearbeiten] Art der Anordnung

So ganz korrekt ist die obige Aussage aber doch nicht - es gibt nämlich nicht nur die Funktion gtk_box_pack_start, sondern auch gtk_box_pack_end. Diese macht nichts anderes als gtk_box_pack_start, nur dass sie die Elemente am Ende hinzufügt. Tauschen wir also das start gegen ein end aus, ist die Reihenfolge plötzlich umgekehrt. Dies liegt daran, dass GTK versucht, ein neues Element so weit an den Anfang oder ans Ende - je nach Funktionsaufruf - zu stellen, wobei zuerst hinzugefügte Elemente höhere Priorität haben.

Was tun die Parameter bei der Erzeugung der Box und beim Hinzufügen von Kindelementen? Die Rede ist selbstverständlich von jenen, von denen man sich die Bedeutung noch nicht selbst erschließen konnte. Beim Hinzufügen neuer Elemente handelt es sich dabei um Parameter für die Ausdehnung, das Ausfüllen und den Abstand. Zweiterer wirkt sich nur aus, wenn ersterer auf true gesetzt wurde. Er bewirkt, dass der zusätzliche Platz, der durch die erste Option zur Verfügung gestellt wurde, auch für das Element benutzt wird, anstatt es nur auszufüllen.

Um dies zu verstehen, muss man weiter denken: Praktisch jedes Element in GTK hat einen Mindestbedarf an Platz. Bei einem Label ist dies zum Beispiel der Platz, der benötigt wird, um den Text komplett anzuzeigen. Unter dieses Minimum kann man nicht gehen - Fenster kann man beispielsweise nicht weiter verkleinern, wenn der Platz nicht für alle Elemente reicht.

Elemente können sich aber auch ausdehnen. Das heißt, wenn ihnen mehr Platz zur Verfügung gestellt wird, dann nutzen sie ihn auch (sofern das nicht durch spezielle Layout-Elemente eingeschränkt wird). Ein Label könnte sich so zum Beispiel Zeilenumbrüche sparen, da der Text in eine Zeile passt, wenn das Label breiter ist.

Wenn beim Hinzufügen von Elementen zu Boxen nun für einzelne festgelegt wird, dass sie sich ausdehnen sollen, dann bekommen die anderen Elemente nur den Mindestplatz, den sie beanspruchen. Der verbleibende Platz wird dann gleichmäßig zwischen den ausdehnenden Elementen aufgeteilt.

Für manche Elemente macht es sogar tatsächlich Sinn, dass die Elemente mit Extraplatz ihre Größe nicht ändern, beispielsweise bei Bildern (aber da gibt es natürlich Ausnahmen). Aber für Labels ist es üblicherweise sinnvoll, dass sie den gewonnenen Platz auch ausnutzen, und das erledigt der zweite Parameter der drei angesprochenen. Andernfalls würde der Platz zwischen den Elementen einfach mit Leerraum aufgefüllt werden.

Der dritte Parameter setzt den Innenabstand des Elementes zu seinem zugewiesenen Platz. CSS-Programmierern kann man hier das Stichwort padding nennen, allen anderen sei gesagt, dass dies Leerraum einer bestimmten Größe ist, der zwischen dem Inhalt und dem Rand eingefügt wird.

Beim Anlegen von Boxen gibt es auch noch diese zwei ominösen Parameter. Der erste legt fest, dass alle Elemente ihren Platz gleichmäßig aufteilen, anstatt standardmäßig nur den Mindestplatz zu beanspruchen und nur mehr Platz zu fordern, wenn er auch vorhanden ist. Der zweite legt den Abstand zwischen jeweils zwei Elementen fest.

[Bearbeiten] Komplexere Layouts

Selbstverständlich kann man auch Boxen in Boxen packen. Nur so entstehen komplexere Anordnungen. Dazu legt man einfach eine zweite Box an und setzt sie als Kindelement der ersten Box.

[Bearbeiten] Von Spacing und Padding

Grundsätzlich - und nicht nur bei der Arbeit mit Boxen - bezeichnet das Spacing den Abstand von Kindelementen, das Padding den Leerraum um ein Element herum.

[Bearbeiten] Übungsaufgaben

Die Lösungen zu den Aufgaben findest du auf der Lösungsseite.

So könnte der "Dateimanager" aussehen.
So könnte der "Dateimanager" aussehen.
  • Schreibe das Grundgerüst für einen Dateimanager mit Menüleiste und drei Dateien. Die Leiste und die Dateien können als Labels dargestellt werden. Die Leiste soll sich ganz oben im Fenster befinden und die gesamte Breite ausnutzen, darunter soll ein Feld sein, welches die Dateien nebeneinander anzeigt. Alle sollen den gleichen Platz einnehmen, einen Abstand von 20 Pixeln haben sowie einen Innenabstand von 10 Pixeln.
Persönliche Werkzeuge