Você está na página 1de 5

Programação Gráfica em C: Gnome Tool Kit (GTK+)

Se você gostou da pequena série de textos sobre programação gráfica usando a Win32
API (aqui, aqui e aqui), saiba que apenas arranhei o assunto, mas toda a base está lá…
Até mesmo para ambientes diferentes como X11, no Linux e Unixes em geral. É claro que
a coisa toda é um pouco mais simples e diferente nesses outros ambientes.
No caso do Linux (e Unixes) o ambiente gráfico não é integrado ao sistema operacional.
Trata-se de um software “servidor” ou daemon. A aplicação literalmente envia comandos
para o daemonpedindo para desenhar uma janela, movê-la, mudar de tamanho, pintar
uma área e o daemonmanda mensagens de volta… Em essência, é o que o Windows
também faz. Mas, no X11, as janelas são desenhadas por um desktop environment
manager, que é um módulo que roda sobre o daemon X11. Existem vários: Gnome, Unity,
Wayland, Cinnamon, MATE, KDE, XFCE, WindowMaker,Motif etc.
Os dois desktop managers mais famosos e mais aceitos são Gnome e KDE e, por isso, as
duas bibliotecas mais usadas para desenvolvimento “em janelas” para Linux são o GTK+ e
o Qt. O primeiro é uma conjunto de bibliotecas para serem usadas em C. A outra, é uma
class library, um conjunto de bibliotecas para serem usadas em C++. Neste aspecto, o
GTK+ é mais parecido com a Win32 API do que o Qt. Eis um “hello, world” com o GTK+:

#include <stdlib.h>
#include <gtk/gtk.h>

int main(int argc, char *argv[])


{
GtkWidget *mainWindow;
GtkWidget *label;

gtk_init(&argc, &argv);

// Cria a janela, ajusta o tamanho, o título e


// conecta o evento "destroy" à função gtk_main_quit.
mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(mainWindow),
320, 200);
gtk_window_set_title(GTK_WINDOW(mainWindow),
"Hello App");
gtk_signal_connect(GTK_OBJECT(mainWindow),
"destroy",
GTK_SIGNAL_FUNC(gtk_main_quit),
NULL);

// Cria o label e ajusta o texto.


label = gtk_label_new(NULL);
gtk_label_set_text(GTK_LABEL(label), "Hello, world!");

// Adiciona o label à janela.


// Mostra a janela e seus filhos.
gtk_container_add(GTK_CONTAINER(mainWindow), label);
gtk_widget_show_all(mainWindow);

// Loop principal.
gtk_main();

return EXIT_SUCCESS;
}

Para compilar é sempre bom usar um utilitário que nos dará a lista de diretórios onde
acharmos os headers e as libraries:

$ pkg-config --cflags gtk+-2.0

-pthread -I/usr/include/gtk-2.0
-I/usr/lib/x86_64-linux-gnu/gtk-2.0/include \

-I/usr/include/gio-unix-2.0/ -I/usr/include/cairo
-I/usr/include/pango-1.0 \

-I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1


\

-I/usr/include/libpng12 -I/usr/include/gdk-pixbuf-2.0
-I/usr/include/libpng12 \

-I/usr/include/pango-1.0 -I/usr/include/harfbuzz
-I/usr/include/pango-1.0 \

-I/usr/include/glib-2.0
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include \

-I/usr/include/freetype2

$ pkg-config --libs gtk+-2.0

-lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo \

-lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0


-lglib-2.0 \

-lfontconfig -lfreetype

Impressionante, não? GTK+ exige um porrilhão (como sempre, essa é uma especificação
de grandeza! hehe) de diretórios contendo arquivos header e um punhado de bibliotecas!
Para compilarmos o nosso programinha podemos misturar as opções --cflags e --libs em
uma linha só, assim:

$ gcc -O3 -s -o hello hello.c `pkg-config --cflags --libs gtk+-2.0`

Estou usando as opções -O3 e -s para otimizações e eliminar símbolos não necessários no
arquivo binário final. O resultado da execução de hello é esse:

Agora, mova a janela, mude o tamanho, minimize, maximize… tá tudo lá num pequeno
executável de 10 KiB!

O que pode surpreender é o aparente uso de Orientação a Objetos em um código em C.

Os macros GTK_WIDGET, GTK_WINDOW e GTK_LABEL são apenas type castings para


que a função não reclame que estamos passando o tipo errado e, ao mesmo tempo, todo
objeto visível é um widget(GtkWidget).

Para tornar as coisas mais rápidas, a identificação de cada objeto é, de fato, um ponteiro
que aponta para ele próprio. Nada de “handles”, como no Win32. E, embora pudéssemos
criar nosso próprio loop de mensagens, GTK+ fornece a função gtk_main() que faz isso
por nós. Ele permite registrar callbacks para hooks no loop, como exemplo, quando o loop
estiver esperando por mensagens, pode executar uma função idle…

Ahhh… quanto ao pkg-config, use a opção --list-all para ver todas as bibliotecas que ele
consegue obter as listas de headers e libs…

Por que gtk_init() toma ponteiros para argc e argv?

A função gtk_init() pode receber opções da linha de comando diretamente para ele… No
caso do X11, por exemplo, a opção --display indica o daemon onde as janelas serão
criadas (pode estar em outra máquina, por exemplo!)… A função retira da lista de
parâmetros aqueles que são destinados apenas ao GTK+!

Um aviso sobre o sistema de coordenadas usado no GTK+:

Se você já mexeu com Applets em JAVA, deve se lembrar da antiga biblioteca AWT
(Abstract Widget Toolkit). Ele foi “copiado” de bibliotecas como XLib e GTK+… Os
containers do GTK+ (GtkWindow, por exemplo) usam o sistema de coordenadas
“geográfico” por default, onde, ao inserir um único widget-filho ele é colocado no “centro”,
ocupando a área útil toda… mas, podemos colocá-lo ao norte, ao sul, ao leste ou oeste,
assim como era feito no AWT.

Isso não significa que não podemos usar um sistema de coordenadas cartesiano, mas,
para isso, precisaríamos incluir o container GtkFixed na nossa janela e esse container é o
que permite posicionamento cartesiano… A maioria das aplicações feitas com GTK+ não
fazem isso…

Existe um utilitário para desenhar janelas?

Sim… existe o Glade:

Screenshot do Glade
Ele gera um arquivo XML contendo a descrição de sua janela e o GTK+ possui funções
que interpretam esse XML e montam a janela completa (GtkBuilder). É a perfeita
implementação do MVC. O View é apenas o arquivo XML contendo a parte visual e o
código que lida com ele é o seu Model e Controller. Num outro artigo explico como
usá-lo…

Gtk+ é portável!

Um detalhe final é que GTK+ é portável. Existe o GTK+ para Linux, OS/X, FreeBSD, mas
também tem para Windows! Isso quer dizer que você pode criar programas gráficos para
todas as plataformas com o mesmo conjunto de bibliotecas. No caso do Windows, terá que
usar o MinGW para compilar com o GCC e carregar junto um caminhão de DLLs que
colocará em C:\Windows\System32 (aqui é mostrado como)… Note que é perfeitamente
possível compilar sua aplicação com GTK+ usando o Visual Studio.

Note que, no Windows, não é necessário usar aquela construção biruta de WinMain(). O
bom e velho main funciona!

GTK+ 2.0 e GTK+ 3.0

Existem duas implementações da biblioteca porque existem, hoje, dois “Gnomes” (versão
2.x e 3.x) diferentes… O ‘G’ do GTK vem de Gnome e é para desenvolver aplicações para
ele que a biblioteca existe. Clique nos links para obter documentação de referência a
ambas as versões: GTK+ 2.0 e GTK+ 3.0. Note, também, que a GLib é parte integrante e,
portanto, uma pancada de algoritmos está à sua disposição (listas, árvores etc)…

Você também pode gostar