Putting things together

Rather than explicitly designing the layout of an application, defining the specific coordinates and dimensions of each element of the application, GTK+ uses relative positioning to indicate the placement of objects relative to each other. "Packing boxes" are the main object used to achieve this.

GTK+ uses a hierarchy of structures, with inherited properties passed down in an object-oriented fashion. All structures in GTK+ are type GtkObject, the root type, and most objects that perform some function are type GtkWidget, (other objects may be type GtkData). Of the various "widgets", those into which other objects may be places (e.g. a label inside a button) are type GtkContainer. However, a container may only contain one object. In order to draw several objects at once, we typically use a packing box, type GtkBox.

There are two main kinds of packing boxes, a vertical box (GtkVBox) and a horizontal box (GtkHBox). Any number of other objects may be packed into these boxes, and are displayed vertically or horizontally, respectively. Two-dimensional tables (GtkTable) may also be used to align objects both horizontally and vertically at the same time. The spacing between objects in a box or table may be defined when the container is created.

The sample code below provides a simple example. After initialising GTK+ using gtk_init (&argc, &argv), which allows standard GTK+ command line options to be processed for setting the appearance of the application, the main window is created. It is type GtkContainer, and so only one object may be placed inside it. We placed a HBox inside it, which is then able to hold two buttons, one which writes a simple message to standard output, the other quits the program. Each object must be passed through gtk_widget_show() to actually appear on the screen. This is typically done in "reverse" order - buttons first, then the box they are contained in, then the whole window that the box sits in - to avoid flickering as each object appears in turn on the screen. This point is more of a issue for older, slower machines.

Note how the same printing function was attached to both buttons, with extra data passed to the function to distinguish between the two. Note also how two different functions (print and quit) are attached to the same "clicked" signal for the "Quit" button. They are executing in the order they were attached. Note lastly how the same variable (GtkWidget *button) is used to refer to both buttons. Once the first button is set up and there is no more need to refer to it, the variable pointing to it can be recycled.

#include <gtk/gtk.h>

void WriteMessage( GtkWidget *widget, gpointer   data )
{
  g_print ("%s was pressed\n", (char *) data);
}


int main( int   argc,
	  char *argv[] )
{
  /* GtkWidget is the storage type for widgets */
  GtkWidget *window;
  GtkWidget *button;
  GtkWidget *box;

  gtk_init (&argc, &argv);

  /* Create a new window */
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  gtk_window_set_title (GTK_WINDOW (window), "Sample GTK+ Application");
  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
           
  /* It's a good idea to do this for all windows. */
  gtk_signal_connect (GTK_OBJECT (window), "destroy",
		      GTK_SIGNAL_FUNC (gtk_exit), NULL);

  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
		      GTK_SIGNAL_FUNC (gtk_exit), NULL);

  /* create packing box */
  box = gtk_hbox_new(FALSE,10);

  /* Create a new button */
  button = gtk_button_new_with_label ("OK");

  /* Connect the "clicked" signal of the button to our callback */
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (WriteMessage), (gpointer) "OK button");
  gtk_widget_show(button);
  gtk_box_pack_start (GTK_BOX (box), button, TRUE, FALSE, 10);
  
  /* Create a new button */
  button = gtk_button_new_with_label ("Quit");

  /* Connect the "clicked" signal of the button to our callback */
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (WriteMessage), (gpointer) "Quit button");
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
  gtk_widget_show(button);
  gtk_box_pack_start (GTK_BOX (box), button, TRUE, FALSE, 10);

  /* show all our widgets */
  gtk_widget_show(box);
  gtk_container_add (GTK_CONTAINER (window), box);
  gtk_widget_show (window);

  /* Rest in gtk_main and wait for the fun to begin! */
  gtk_main ();

  return(0);
}


Previous: First things in GTK+
Next: Compiling GTK+ Applications
Back to index