As Big As This

Alalalalala

Changing the Basic Window

In the last lesson, we learned the basic structure of a GTK Window. We also learned how to set the text that appears in the title bar. This time, we’ll go a small step further; we’ll change the window size as well as its position, set an icon for our program, create a basic menu, and finally destroy the program properly,

Center and Set Window Size

The code to do this is:

gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

You may have already guessed, 400 is the width and 300 is the height, which we will set as the default size of our window. For the initial position, you may have noticed that one of the parameters is the constant GTK_WIN_POS_CENTER, which, you guessed it, centers the window.

Set Window Icon

The following is the function used for setting the window icon, using 2 parameters: the window, and a Gdk Pixelbuffer object.

gtk_window_set_icon(GTK_WINDOW(window), pixbuf);

The problem is converting your desired graphic into something useable as an icon. Here we borrow a function from Zetcode’s First Programs tutorial (see References) which accepts a filename as a parameter and returns a GdkPixbuf object:

GdkPixbuf *create_pixbuf(const gchar * filename)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(!pixbuf) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
}
return pixbuf;
}

The gdk_pixbuf_new_from_file() functions takes two parameters–the filename of the image, and a GError object where it’ll put an error message if something goes wrong. It automatically detects the filetype of the file and convert it into a GdkPixbuf object.

We make a call to the create_pixbuf() function as follows:

gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("mylogo.gif"));

You can replace mylogo.gif with your own GIF, PNG, BMP, or JPG file.

Create a Menu

As mentioned in the first post, GTK uses hierarchies and containers quite extensively, and menus and submenus are no different. A menu is basically a container where you can put in items or even other containers i.e. submenus. The basic logic behind putting a menu into your GTK application is that the window itself is a container, and you attach a box container that will hold your menubar (itself a container), which will hold your menu (another container), which holds your menu items or even submenus (yet another container).

I did not grasp this relationship immediately when I studied it, so here I present the sample code relating to that hierarchical relationship. It may not be the best coding standard (personally, I prefer to put all my variable declarations together at the beginning), but for the sake of easier understanding, we’ll put relevant objects as they are needed and being built.

First, we create the menu items like so by creating new GtkWidgets and initializing them like so:

//Initialize the File menu items
GtkWidget *file;
GtkWidget *open;
GtkWidget *quit;
file = gtk_menu_item_new_with_label("File");
open = gtk_menu_item_new_with_label("Open...");
quit = gtk_menu_item_new_with_label("Quit");

Next, we create the File menu to hold our menu items:

//Initialize File menu and put in the menu items
GtkWidget *filemenu;
filemenu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);
gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), open);
gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);

Take note that we are actually setting first item (file) as a submenu. The open and quit menu items are then added to the filemenu using the gtk_menu_shell_append() function.

Next, we put our File menu into the menu bar:

//Initialize the menu bar and put in the File menu we created
GtkWidget *menubar;
menubar = gtk_menu_bar_new();
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);

Now that everything’s almost set, we have to put our menubar on to the window itself:

//Put the menu bar into the window
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3);

vbox is initialized into a GtkVBox object, which is a vertical container box. No, I don’t know either why they called a horizontal-looking box a vertical container box. I guess we’ll learn that soon enough. Anyway, gtk_container_add() adds the vbox container to the window (our big, main container) and gtk_box_pack_start() packs our menu bar into our box.

Closing the Window Properly

In our last lesson, although clicking on the close button makes the window disappear, it doesn’t actually destroy the program. We have to connect the destroy signal to the gtk_main_quit function().

g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

If you noticed, the Quit button doesn’t close our program, even if we have just set the callback for the destroy signal event. That’s because the Quit menu item is just a menu item like Open. Until we tell it what to do, it does nothing. The signal we actually have to listen for is not the destroy signal, but the activate signal, which is sent whenever you click on a menu item. So we connect the quit object’s “activate” signal to the gtk_main_quit() function, which we already know will terminate our program nicely.

g_signal_connect(G_OBJECT(quit), "activate", G_CALLBACK(gtk_main_quit), NULL);

Summing Up

Our program which contains the previous Hello Wolrd lesson, as well as the new window size and position, icon, menu, and proper destruction on exit should look something similar to this:

#include <gtk/gtk.h>

GdkPixbuf *create_pixbuf(const gchar * filename)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(!pixbuf) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
}
return pixbuf;
}

int main (int argc, char **argv) {
gtk_init(&argc, &argv);

//Basic Window Setup
GtkWidget *window;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hello, World");
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("mylogo.gif"));

//Initialize the File menu items
GtkWidget *file;
GtkWidget *open;
GtkWidget *quit;
file = gtk_menu_item_new_with_label("File");
open = gtk_menu_item_new_with_label("Open...");
quit = gtk_menu_item_new_with_label("Quit");

//Initialize File menu and put in the menu items
GtkWidget *filemenu;
filemenu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);
gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), open);
gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);

//Initialize the menu bar and put in the File menu we created
GtkWidget *menubar;
menubar = gtk_menu_bar_new();
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);

//Put the menu bar into the window
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3);

//All set. Display all.
gtk_widget_show_all (window);

//Connect the destroy signal to the gtk_main_quit() function
g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

//Connect the "quit" object's "activate" signal to the gtk_main_quit() function
g_signal_connect(G_OBJECT(quit), "activate", G_CALLBACK(gtk_main_quit), NULL);

gtk_main();
return 0;
}

References:

October 19, 2008 Posted by | GTK Programming, GTK Tutorials | 5 Comments

Saying Hello World With GTK

So now we’ re going to start nice and easy by making a common, household Hello World application. Here I’ll lay out a bare-essentials GTK application which I will try to explain as breifly as I can so fire up your text editor and create a base.c file:

This tells your compiler to include the gtk header files which includes the variables, structures, and other neat stuff in the GTK toolkit.

#include <gtk/gtk.h>

Here we have your main application function declaration. It has two parameters, which are pretty much standard:

int main(int argc, char **argv)
{

Here we declare an instance of GtkWidget which is a storage type for widgets and we’ll name it window:

GtkWidget *window;

Next, we call gtk_init, which as the name implies initializes GTK, initializing such stuff like color space, libararies, default signal handlers, etc. Here we see argc and argv again, which contain the arguments passed from the command line. gtk_init parses these arguments for special reserved arguments and removes them from the argument list. That’ll be useful in our future programs, so take note:

gtk_init (&argc, argv);

This creates a new window:

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

And this one shows the window:

gtk_widget_show (window);

Last, but certainly not the least, calling this gets us into the main processing loop:

gtk_main ();

And, then we elegantly close off our function

return 0;
}

Ok, put that all together and compile using the following basic compile command:

gcc base.c -o base `pkg-config --cflags --libs gtk+-2.0`

After it compiles, you’ll have a program that you can either double-click, or in terminal type

./base

This will open up a window with the default 200×200 size because we didn’t specify a size. But wait, it say’s base on it’s title bar, not “Hello World”! Yes, that’s just the bare-essential base application we did. We need to add these right before gtk_window_show:

gtk_window_set_title (GTK_WINDOW (window), "Hello, World");

Compile it again, and we have our extremely easy Hello World program.

Hello World In Three Flavors

In one of my previous posts I mentioned that GTK is language-neutral, so you may be wondering why this code looks an awful lot like C. That’s because I prefer to code in C, but you can just as easily code this in C#, Ruby, Perl, or others by referring to the GTK Hello World In Six Different Languages article on which this tutorial was based on. Just scroll down and click on the link in my references below.

Next >> Changing The Basic Window

References:

February 29, 2008 Posted by | GTK Programming, GTK Tutorials | Leave a comment

Setting Up Your GTK Workspace

Alright, so onto the meat of things! Before any of the magic happens, I need to set up my system so that I can actually build something.

Several months ago, I first tried doing this by reading the GTK Tutorial (also in my links), and it said I needed to download GTK source from the GTK website and install it from source. Needless to say, I had too much power in my hands than I knew what to do with and I trashed my Ubuntu box. Ok, so we’ll do this the easy way: Synaptic

Installing GTK Packages Via SynapticOpen up your Synaptic Package Manager and look for libgtk2.0-0, it should already be installed. Check to be sure. There should be several similar packages already installed, but the most important package is the libgtk2.0-0-dev. Hmm, I’ll install libgtk2.0-0-doc for good measure as well. Iwas going to install the libgtk2.0-0-dbg, too, but the package description says most people won’t need this, so scrap that.There are several more, but I think this is enough to get started.

After marking the packages (Synaptic will prompt you that it needs several more packages to install libgtk2.0-0-dev), click on the Apply button and we’re done! Man, this tutorial could be more interesting if it was just a little bit harder. On the other hand, at least I’m sure this won’t trash my desktop. Oh well.

[Edit] I forgot to say thanks to Kostkon and Compyx in the Ubuntu Forums for pointing me in this direction. Thanks!

Next >> Saying Hello World with GTK

February 28, 2008 Posted by | GTK Tutorials | Leave a comment