Sunteți pe pagina 1din 21

• Python é uma linguagem interpretada, orientada a objetos, extensível e de fácil utilização.

GTK+ (Gimp Tool Kit) é uma

biblioteca para criar interfaces gráficas.


Para utilizá-las em conjunto, foi criado o PyGTK, que consiste em uma série de módulos para prover uma interface ao
Python para acesso ao GTK, possibilitando ao desenvolvedor a criação de sistemas com interfaces gráficas riquíssimas.

Lição 1 - Apresentando PyGTK

Embora o curso assuma um certo conhecimento de Python, não é necessário que o aluno tenha experiência com GTK+.
Entretanto, isto não nos impede de oferecer uma visão geral de todos os componentes envolvidos.

GTK+

O GIMP Toolkit, popularmente conhecido por GTK+, é um dos mais famosos toolkits voltados para a criação de interfaces
gráficas (referidas GUIs daqui em diante). O que, então, justifica a parte GIMP do nome? Originalmente, foi idealizado para
servir de base para o editor de imagens GIMP (GNU Image Manipulation Program), mas acabou expandindo muito além.
O GTK+ é um dos pilares do famoso ambiente de janelas GNOME, portanto aplicações baseadas nesta biblioteca podem ser
facilmente identificadas pelo visual em comum.
Seus autores incluem Spencer Kimball, Peter Mattis e Josh MacDonald, todos os quais trabalhavam na Universidade de Berkeley
à época de criação do GTK+/GIMP.
Exemplo de aplicativo GTK+

Os menus, botões, formulários, dropdowns e outros elementos da janela (widgets) possuem um visual bastante padronizado,
mesmo entre os vários temas disponíveis no GTK+ (acima representado está o tema padrão da distribuição Ubuntu).

Python

Pythonidae é uma família de répteis escamados da subordem Serpentes. O grupo inclui diversas espécies de cobras constritoras

Python é uma linguagem de programação de alto nível orientada a objetos. Seu criador, Guido van Rossum, a criou em 1991
com o objetivo de enfatizar o esforço do programador sobre o esforço computacional, tornando-se uma linguagem de fácil
aprendizagem.
Além do mais, Python se difere de outras linguagens no quesito simplicidade e legibilidade. Por exemplo, a indentação do código
é de prima importância para que o código execute corretamente, o que conseqüentemente facilita bastante a sua compreensão e
padroniza os programas com um look similar. O caractere ; não é necessário para indicar o término de um comando, servindo a
quebra de linha (\n) para tal.
Quanto ao aspecto de simplicidade, isto apenas se aplica ao núcleo da linguagem. Há uma vasta quantidade de bibliotecas
disponíveis, inclusive distribuídas com o Python. Uma destas, aliás, é o...

PyGTK

Como o leitor mais atento deve ter percebido, o objetivo deste curso é aliar o Python e o GTK+ através da biblioteca PyGTK.
Dispensando explicações sobre a origem de seu nome, partiremos para um overview geral.
O PyGTK é um conjunto de wrappers (vulgarmente "envoltórios") para a biblioteca GTK+. Assim como o Python, o PyGTK é
software livre, no entanto é distribuído sob a licença LGPL. É de autoria de um dos desenvolvedores do GNOME, James
Henstridge, e hoje possui uma equipe maior, inclusive com grande participação da comunidade através de patches e bug reports.
Um dos méritos do PyGTK é ter sido escolhido como o ambiente de escolha para aplicações rodando nos sistemas do projeto One
Laptop Per Child. Além disso, algums outros projetos usam o PyGTK, tais como:

• Instalador Anaconda (usado no Fedora)


• Bittorrent (cliente)
• GNOME Sudoku (ótimo passatempo)

Talvez a melhor forma de se passar a conhecer uma ferramenta previamente desconhecida seja instalando-a, e em seguida
rodando um simples exemplo para testá-la e familiarizar-se com o que está por vir.
É exatamente o que será feito.

Instação

O Linux é, decididamente, a plataforma ideal para este tipo de desenvolvimento e é a que nós recomendamos. Não obstante,
usuários de Windows podem seguir com o curso, assim como os de Mac OS X. Apenas a etapa de instalação deverá diferir do
que está apresentado no curso. (Devido à indisponibilidade de recursos, a tarefa de instalçao será deixada por conta do
usuário.)

Linux

Talvez até excessivamente simples, para se instalar o PyGTK nas distribuições Debian e derivados (tais como Ubuntu), basta
instalar o pacote python-gtk2:

apt-get install python-gtk2

Isto irá instalar as bibliotecas necessárias. Caso seja solicitado para instalar pacotes dependentes, aceite.
Caso esteja usando outra distribuição, procure um pacote com este nome ou pygtk.
OK, tecnicamente estamos prontos para seguir em frente e aprendermos os conceitos. Mas primeiro vamos verificar se a etapa
de instalação realmente foi concluída com êxito.

Crie um arquivo com o seguinte código usando seu editor predileto:


import pygtk

import gtk

# Teste inicial

class Janela:

def __init__ (self):


self.janela = gtk.Window(gtk.WINDOW_TOPLEVEL)

self.janela.show()

def main (self):

gtk.main()

if __name__ == "__main__":

janela = Janela()

janela.main()

Salve-o como "testando123.py" e execute-o (python testando123.py).

Enfrentou algum problema? Envie sua dúvida ao fórum! Não será possível prosseguir com o curso se este exemplo não
funcionar.

Não se preocupe com o código, iremos detalhá-lo mais adiante.

Perceba que este exemplo apenas exibe uma janela vazia. Nem mesmo o botão de fechá-la funciona. Veremos os motivos mais
adiante.

Lição 2 - Apresentando Widgets, Signals e Callbacks

Antes de prosseguirmos com os exemplos, iremos dar uma breve olhada nos conceitos que serão explorados. Estes são de
crucial importãncia para o entendimento pleno da matéria. Usuários que não possuem experiência prévia com GTK+: leiam esta
página atenciosamente.

Widgets

Um conceito extremamente simples; derivado de window gadets (apetrechos de janela), o termo pode representar qualquer
elemento de uma janela, tais como botões, barras de rolagem, menus dropdown, campo de texto, barra de título, barra de
ferramentas e qualquer outra parafernália que pode estar contida em uma janela. Em suma, tudo representado é um widget.

Sinais, callbacks e eventos

Sinais

O GTK+ é um chamado event-driven toolkit, significando que uma vez que se atinge o gtk.main(), o processo adormece até que
um evento ocorra e o controle seja redirecionado para a função correspondente. Este conceito é denominado sinal (entretanto
este conceito é meramente semelhante aos signals Unix, a implementação é bastante diferente). Quando ocorre um evento,
como o apertar de um botão, o widget irá emitir um sinal. Os sinais variam de widget para widget. Por exemplo, o botão herda
sinais de várias classes:

• gobject.GObject: "activate", "clicked", "enter", "leave", "pressed" e "released".


• gtk.Object: "destroy"
• gtk.Widget: "accel-closures-changed", "button-press-event", "button-release-event", "can-activate-accel", "child-notify",
dentre muitas, muitas outras.
• gtk.Container: "add", "check-resize", "remove", "set-focus-child"

Para o exemplo do botão, a lista completa de sinais pode ser encontrada em: http://www.pygtk.org/docs/pygtk/class-
gtkbutton.html#signal-prototypes-gtkbutton.
Percebe-se que a quantidade possível de sinais é imensa para um dado widget, e neste curso iremos ver apenas os signals mais
freqüentemente utilizados.

Callback
Quando um sinal ocorre, uma função callback pode ser acionada. Esta função pode alterar a interface, abrir uma janela popup,
fechar o programa, conectar a um banco de dados... enfim. É o elo entre os widgets e o resto do programa. Como, então,
associar uma função callback a um signal? Para tal, os objetos em GTK possuem a função connect:

handler_id = object.connect (name, func, func_data)

Nesta linha, object é a instância do GtkWidget que estará emitindo o sinal, e o primeiro argumento (name) indica o nome do
sinal que irá acionar o callback (por exemplo "clicked" ou "destroy"). O segundo argumento (func) indica a função (callback) que
deverá ser acionada. Repare que o argumento é o *objeto* da função, e não o seu nome. No terceiro argumento, estão os
dados que serão repassados para a função.
Portanto o callback deverá ter o seguinte cabeçalho:
def callback_func (widget, callback_data)
O primeiro parâmetro será um ponteiro para a widget que emitiu o sinal, e o segundo parâmetro um ponteiro para os dados
definidos na chamada do connect.
Naturalmente, se a função callback for definida em um método, sua forma geral será:
def callback_func_method (self, widget, callback_data)
Onde self representa a instância do object acionando o método.
(Existem exceções quanto aos seus argumentos, mas de forma geral serão estes.)
Juntos, estes dois conceitos (signals e callbacks) formam boa parte dos fundamentos por trás do GTK+.

Eventos

Além dos sinais, existem também eventos, que refletem o mecanismo de eventos do X. São muito similares a sinais, no sentido
que callbacks também podem ser associados a estes. Refletem eventos tais como o requisitado fechamento de um programa, ou
o clique do mouse (ou duplo-, triplo-clique). No entanto, o cabeçalho de suas funções callback é um pouco diferente:

def callback_func (widget, event, callback_data)

ou, no caso de uma função callback definida em um método:

def callback_func_method (self, widget, event, callback_data)

Como fazer para conectar uma função callback a um evento? Usando connect:

handler_id = object.connect (name, func)

Por exemplo, para um botão pode-se definir o evento da seguinte forma:

handler_id = botao.connect ("button_press_event", button_click_event)

No momento do evento, isto iria invocar a seguinte função:

button_click_event (widget, event, callback_data)

O valor que esta função retorna indica se o evento deverá ser propagado pelo mecanismo de gerenciamento de eventos do
GTK+. Se retornar True, significa que o evento já foi tratado e não deverá propagar. (Isto é, se houver mais de um callback
associado a um evento.) Se retornar False, então o evento será propagado.

Se isto ainda está um pouco nebuloso, não se preocupe. Exemplos tornarão os conceitos bem mais claros.

Desconectando callbacks

É claro, também é possível desassociar um callback de um sinal ou um evento. O comando a ser usado é o seguinte:

object.disconnect (handler_id)

Agora que temos um embasamento teórico podemos partir para exemplos.

Crie um arquivo com o nome botao1.py com o seguinte conteúdo:


#!/usr/bin/env python# -*- coding: latin-1 -*-

import pygtk
import gtk

class Janela:
def __init__ (self):
""" Primeiro criamos uma janela do tipo WINDOW_TOPLEVEL. Isto é feito através da geração de uma instância da classe Window.
"""
self.janela = gtk.Window (gtk.WINDOW_TOPLEVEL)
""" Ajustamos alguns parâmetros referentes à janela: - Ajusta o espaçamento da borda para 10 (espaço entre borda e os
widgets - Seta o título da janela - Altera o tamanho da janela"""
self.janela.set_border_width (10)
self.janela.set_title ("Pythonizando GTK+")
self.janela.resize (300, 100)
""" Associa o callback self.delete_event ao evento delete_event. Caso isso não fosse feito, o programa continuaria sua execução
mesmo após o fechamento da janela """
self.janela.connect ("delete_event", self.delete_event)
""" Em seguida cria-se um botão (perceba que é a isntância de uma classe. """
self.botao = gtk.Button ("Hey there")
""" IMPORTANTÍSSIMO: (quase) todo elemento deve ser explicitamente exibido para que apareça na tela. """
self.botao.show ()
""" Adiciona o botão á janela. Para adicionar mais elementos será necessário criar um container, como veremos adiante """
self.janela.add (self.botao)
""" Exibe a janela (e consequentemente tudo contido nela). """
self.janela.show ()
def delete_event (self, widget, event):
gtk.main_quit()
return False
def main (self):
gtk.main()
if __name__ == "__main__":
janela = Janela()
janela.main()

O resultado será algo assim:

A maior parte do código é bastante intuitiva; a criação da janela, atribuição de parãmetros, criação do botão. Há 2 elementos
importantes neste exemplo: o callback e as chamadas a show().

O método show() causa uma widget a ser exibida assim que possível. Antes de se chamar este método a widget não será
mostrada! Naturalmente, para que uma widget seja visualizada, é necessário também que todos os containers da widget
também sejam explicitamente mostrados. Quando um container "toplevel" (que contém outros widgets) é mostrado, este é
imediatamente mapeado e exibido na tela, assim como todos os widgets contidos dentro deste que já estejam exibidos. É por
este motivo que a ordem de chamada deve começar das widgets internas até chegar nas widgets externas; caso contrário o
usuário irá ver a atualização dos componentes dependendo da complexidade gráfica do GUI.

Outro aspecto importante do exemplo é o callback uasdo para o fechamento do programa. O evento "delete_event" é chamado
quando o sistema operacional recebe uma soilcitação de fechamento do programa. Isto pode ocorrer quando o usuário clica no X
para fechar, ou pelo gerenciador de tarefas. Em todo caso, se não tratarmos este evento a widget em questão (no caso a janela
em si) será finalizada, no entanto o gtk.main() continuará sua execução. (Tente isto; remova o self.janela.connect e veja o que
ocorre depois de fechada a janela.) Por esse motivo é necessário explicitamente executar gtk.main_quit(). O dado passado pelo
delete_event (no quarto parâmetro da função callback) é None e portanto é ignorado pela função callback.

Você consegue ver a utilidade disto? Nem sempre que o usuário fecha uma janela ele necessariamente teve tal intenção. O
browser Firefox confirma o fechamento da janela se mais de uma aba estiver aberta. O OpenOffice pergunta se deseja salvar o
documento antes de fechar. É este evento o responsável por essas ações.

Lição 3 - Widgets elementares

Até o momento trabalhamos com apenas uma widget na janela principal. Como fazer para agrupá-las?

Há várias formas de fazê-lo; a mais comum delas são caixas (boxes).

Boxes

Boxes são contêineres transparentes nos quais podem ser empacotados outras widgets. Pode-se usar tanto o HBox (horizontal)
quanto o VBox (vertical). Ao empacotar elementos no HBox eles podem ser inseridos da esquerda para a direita ou da direita
para a esquerda, dependendo da forma como for criado. É comum usar uma combinação de boxes (boxes dentro de boxes) para
criar o efeito desejado.

Como é de se esperar, para criar um HBox basta gerar uma instância de gtk.HBox(). Para adicionar elementos a um box, usa-se
o método pack_start() e pack_end(), onde o primeiro insere da esquerda para a direita e o último da direita para a esquerda.
Boxes podem agrupar tanto widgets quanto outros boxes.

Vale frisar que botões são contêineres por si só, mas normalmente usa-se apenas um label dentro do botão.
Como criá-los

O cabeçalho da HBox() está definido da seguinte forma:

gtk.HBox (homogeneous = False, spacing = 0)

se o primeiro parâmetro for True, isto garantirá que todos os elementos terão exatamente a mesma largura. O segundo
parâmetro especifica o espaçamento entre os elementos.

Além disso, a forma como se agrupa os elementos também altera a aparência geral do layout:

box.pack_start(child, expand=True, fill=True, padding=0)

Box é o container onde o widget será empacotado e o parâmetro child deve ser o objeto do widget a ser empacotado. Os outros
parâmetros controlam como os widgets inseridos se adaptarão ao box (ou vice-versa):

• Expand define se o objeto se ajustará para ocupar todo o espaço disponível no widget (True) ou se o box se reduzirá ao
tamanho dos widgets (False). Se isto for False, é possível manter todos os widgets alinhados no canto direito ou
esquerdo do box.
• O parâmetro fill somente tem efeito se o expand for false; neste caso, ele controla se o espaço remanescente no box
deverá ser alocado como espaçamento entre os widgets (False) ou se os widgets receberão o espaço remanescente
(True).
• Finalmente padding é o espaçamento que será adicionado a ambos os lados do widget.

Qual a diferença entre padding (fornecido no pack_start() ou pack_end()) e spacing (fornecido no HBox() ou VBox())? O
spacing é o espaço adicionado entre os elementos, e o padding é o espaço adicionado a ambos os lados de um elemento.

Toda essa teoria também se aplica ao VBox, invertendo-se os eixos.

Exemplificando

Observe o exemplo a seguir, botao2.py:


#!/usr/bin/env python# -*- coding: latin-1 -*-import pygtk import gtk classJanela: def__init__ (self): # Primeiro criamos uma
janela do tipo WINDOW_TOPLEVEL. self.janela = gtk.Window (gtk.WINDOW_TOPLEVEL) # Ajustamos alguns parâmetros
referentes à janela: self.janela.set_border_width (10) self.janela.set_title (u"Botões 2") self.janela.resize (300, 50) # Em
seguida cria-se os botões self.botao1 = gtk.Button ("Hey there") self.botao2 = gtk.Button ("Au revoir", gtk.STOCK_QUIT) #
Associa o callback self.delete_event ao evento# delete_event. self.janela.connect ("delete_event", self.delete_event) #
Especificamos o argumento data como None self.botao1.connect ("clicked", self.button_click, None) self.botao2.connect
("clicked", self.delete_event, None) # Exibe-os self.botao1.show () self.botao2.show () # Cria-se um HBox homogêneo (todos
elementos ocupam o mesmo# espaço) com espaçamento 10 entre os elementos. self.hbox = gtk.HBox (True, 10) # Empacota os
botões no HBox self.hbox.pack_start (self.botao1) self.hbox.pack_start (self.botao2) # Adiciona o botão à janela. Para adicionar
mais elementos# será necessário criar um container, como veremos adiante self.janela.add (self.hbox) # Exibe o hbox
self.hbox.show () # Exibe a janela self.janela.show () defdelete_event (self, widget, event): gtk.main_quit() defbutton_click
(self, widget, event): print"Hullo"defmain (self): gtk.main() if __name__ == "__main__": janela = Janela() janela.main()
O resultado deve ser o seguinte:

Obviamente pode-se ir muito além disso, encapsulando vários boxes e criando um layout extremamente flexível.

Lição 4 - Widgets miscelâneas 1

Um elemento muito frequente em interfaces com usuários é o "slider", uma barra de rolagem através da qual o usuário pode
escolher uma faixa de valores. Eis um exemplo:

O GTK+ obviamente suporta tais widgets, mas primeiro devemos entender um pouco sobre a teoria por trás de seu
funcionamento.

Adjustments
Uma aplicação necessita reagir às ações de usuários nestes widgets; isto poderia ser feito através de um sinal emitido pela
widget quando houvesse uma mudança no seu valor, no qual a widget transmite também o novo valor para a função
responsável. No entanto, e se quiséssemos associar os ajustes de várias widgets, de tal forma que mudar o valor em uma
widget altera outra? Uma aplicação prática para isto seria conectar as barras de rolagem de tal forma a selecionar o conteúdo a
ser visualizado, por exemplo, de uma imagem. (Será isso um presságio?) Se cada widget de ajuste tivesse de emitir um sinal a
cada mudança de valor, o programador teria de escrever gerenciadores de sinais para transmitir a mudança de valor de uma
widget para outra.

O GTK+ nos auxilia através do objeto Adjustment, que não é uma widget, mas uma forma através da qual widgets podem
transmitir informações sobre ajustes de uma forma abstrata e flexível. Além de guardarem parâmetros de configuração e valores
de widgets (ou várias delas), Adjustments podem emitir sinais, assim como widgets convencionais, e isso pode ser usado para
propagar informações entre várias widgets separadas.

Você já conhece bem esse tipo de widget; são barras de progresso, janelas com barra de rolagem, dentre outros.

Criando um Adjustment

A sintaxe é simples:

adjustment = gtk.Adjustment(value=0, lower=0, upper=0, step_incr=0, page_incr=0, page_size=0)

O parâmetro value indica o valor inicial a ser atribuído à widget. Lower e upper são o menor e maior valores que podem ser
assumidos pelo widget. Step_incr define o intervalo entre os ajustes, page_incr define o maior intervalo entre estes. Finalmente
o page_size é o parâmetro que contém a área visível no caso de uma widget à qual se aplique.
Os widgets ajustáveis podem ser divididos naqueles que necessitam de uma unidade específica (por exemplo pixels) e aqueles
que usam números arbitrários. Alguns widgets que usam números arbitrários incluem a barra de rolagem e a barra de
progresso. Estas podem ser ajustadas pelo mouse ou pelo teclado, e a faixa de valores pode ser definida no ajuste. Por padrão,
manipular tal widget apenas altera o valor de seu Adjustment.
O outro grupo inclui o widget de texto e a janela com barra rolagem. Estes necessitam valores em pixels para seus Adjustments.
Alguns widgets que podem ser ajustados indiretamente usando barras de rolagem, a exemplo do ScrolledWindow que veremos
adiante.
Adjustments podem também ser manipulados manualmente. Para alterar o valor de um objeto Adjustment, usamos

adjustment.set_value(value)

Como já dissemos, Adjustments são capazes de emitir sinais (por serem derivados da classe Object, assim como outros widgets)
e por este motivo mudanças se propagam automaticamente quando por exemplo uma barra de rolagem conectada a outra
widget é alterada; todas widgets ajustáveis se conectam através do sinal value_changed.
Com um pouco de bagagem sobre Adjustments, podemos voltar ao tópico inicial da lição.
Como se pode imaginar, todas as widgets de faixa de valores são associadas a um objeto Adjustment, através da qual estas
calculam as dimensões da barra de rolagem.

Barra de rolagem

São os widgets mais simples desta categoria e é uma das quais mais lidamos. São apropriadas para mudar aspectos de outras
widgets, como uma lista, uma caixa de texto ou um viewport. Para outras funcionalidades (como escolher um valor específico) é
mais recomendável usar widgets de escala, que são mais amigáveis e possuem mais funcionalidades.

Criamo-as através do seguinte comando (horizontal ou vertical):

hscroll = gtk.HSrollbar (adjustment=None)


vscroll = gtk.VSrollbar (adjustment=None)

O parâmetro pode ser um adjustment criado pela função mostrada na seção anterior. Na omissão deste será criado um
adjustment automaticamente, que pode subseqüentemente ser obtido através de funções auxiliares.

Widget de escala

Idêntico ao exemplo dado no início da lição, widgets Scale permitem que o usuário manipule um valor em uma faixa específica.
Pode ser usado, por exemplo, para alterar o zoom de uma página ou o contraste de uma imagem.

Estes widgets possuem 2 tipos: 1 para widgets horizontais outro para widgets verticais. (a versão horizontal é mais comum).
Funcionam exatamente da mesma maneira. Para criá-los:

vertical_scale = gtk.VScale (adjustment=None)


horizontal_scale = gtk.HScale (adjustment=None)

Vê o parâmetro adjustment? É através deste que se pode "linkar" widgets a um adjustment em comum. Caso seja omitido, o
adjustment será criado pela função com todos os valores ajustados em 0.0, o que não é muito útil. Como o page_size pode
afetar o valor máximo da widget (além do especificado pelo parâmetro upper), é recomendado que se ajuste o page_size em 0.0
para que o valor upper coincida com o maior valor que o usuário pode selecionar.
Opções

Algumas widgets de escala exibem o valor escolhido ao seu lado; isto pode ser feito através da seguinte função:

scale.set_draw_value (draw_value)

onde draw_value pode ser True ou False. O número de casas decimais exibido pode ser ajustado através de:

scale.set_digits (digits) (o limite é 13)

Para definir a posição relativa onde o valor será representado, usa-se:

scale.set_value_pos (pos)

onde o argumento pos pode ser qualquer um de POS_LEFT, POS_RIGHT, POS_TOP ou POS_BOTTOM.

Política de atualização

Como você já sabe, o sinal "value_changed" é emitido quando o valor é alterado. Mas quando exatamente é isso? A qualquer
mudança? Apenas quando o usuário pára de mover a barra da widget? Há 3 políticas de atualização:

• UPDATE_CONTINUOUS: emite o sinal value_changed continuamente, mesmo que a barra seja movida muito pouco.
• UPDATE_DISCONTINUOUS: emite o sinal value_changed apenas quando o valor da widget não está em movimento e o
usuário solta o botão do mouse.
• UPDATE_DELAYED: emite o sinal value_changed se o usuário soltar o botão do mouse, ou se a barra ficar parada por um
curto instante.

Para ajustar uma destas políticas faça o seguinte:

range.set_update_policy (policy)

Obtendo e usando um adjustment

Às vezes o adjustment não é criado explicitamente, sendo isto feito através da criação de uma widget que o necessita. Nestes
casos podemos obter o adjustmente através de:

adjustment = range.get_adjustment()

Da mesma forma, para configurar uma widget para usar outro adjustment usamos:

range.set_adjustment(adjustment)

(Perceba que o set_adjustment() não surtirá efeito se o adjustment for o mesmo em uso pela widget, mesmo que seus valores
tenham sido alterados. Para tal seria adequado emitir o sinal "changed" através de adjustment.emit("changed").)
Labels (rótulos) estão entre os widgets mais simples, no entanto são um dos mais frequentemente usados. Simplesmente
exibem texto que não é editável pelo usuário, como usado em um formulário para indicar os campos correspondentes. Para criá-
los:

label = gtk.Label (str)

Onde str deve conter o valor inicial a ser assumido pelo label. Para alterar este texto posteriormente à sua criação:

label.set_text (str)

Da mesma forma pode-se obter o texto já contido em um label:

str = label.get_text ()

Além disso, estas widgets podem exibir texto ao longo de várias linhas quando a str os contém. É possível também fazer com
que a widget automaticamente acrescente as quebras de linha:

label.set_line_wrap (wrap)

Onde o parâmetro pode wrap ser True ou False.


Muitas outras opções são suportadas;
sempre como
recomenda-se referir à documentação original:
http://www.pygtk.org/docs/pygtk/class-gtklabel.html.

Ainda no tópico de adjustments e widgets com faixa de valores, um dos widgets mais úteis que utilizam esse recurso é o
ScrolledWindow. Consiste em uma área (um viewport) sendo que apenas uma parte pode ser exibida. Barras de rolagem nas
laterais permitem que o usuário selecione a área a ser visualizada. (Podem ser omitidas caso a área possa ser exibida na sua
íntegra, tanto no eixo horizontal quanto no eixo vertical.) O melhor de tudo é o fato de tudo isto ser uma única widget! Veja só:

scrolled_window = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)

Os dois parâmetros são os adjustments a serem usados no sentido horizontal e vertical da widget. Usualmente não é necessário
especificá-los.
Para definir quando as barras de rolagem deverão ser exibidas, usa-se

scrolled_window.set_policy(hscrollbar_policy, vscrollbar_policy)

Onde cada um desses valores pode ser POLICY_AUTOMATIC (determina automaticamente se a barra de rolagem deverá estar
disponível) ou POLICY_ALWAYS (sempre estará disponível).
Para adicionar o widget que se deseja exibir ao ScrolledWindow:

scrolled_window.add_with_viewport(child)

Temos a seguir um simples exemplo (misc1.py) que usam os conceitos aprendidos nesta lição. O exemplo não é
particularmente útil, mas ilustra bem os conceitos aprendidos.

#!/usr/bin/env python# -*- coding: latin-1 -*-import pygtk import gtk

classJanela:

def__init__ (self):

# Primeiro criamos uma janela do tipo WINDOW_TOPLEVEL. self.janela = gtk.Window (gtk.WINDOW_TOPLEVEL)

# Ajustamos alguns parâmetros referentes à janela: self.janela.set_border_width (10)

self.janela.set_title (u"Widgets miscelâneos")

self.janela.resize (200, 400)

# Assegura-se que a janela será fechada corretamente.# (Lembre-se de funções lambda em Python!)
self.janela.connect("destroy", lambda wid: gtk.main_quit())

self.janela.connect("delete_event", lambda a1,a2:gtk.main_quit())

# Conteiner de todos os elementos vbox = gtk.VBox (False, 2)

# Widgets de faixa de valores hadjustment = gtk.Adjustment()

vadjustment = gtk.Adjustment()

# Cria os widgets de escala usando o recém-criado adjustment hscale = gtk.HScale(hadjustment)

vscale = gtk.HScale(vadjustment)

hscale.show()

vscale.show()

# Widgets label hlabel = gtk.Label("Ajuste horizontal:")

vlabel = gtk.Label("Ajuste vertical:")

hlabel.show()

vlabel.show()

# Imagem que sera encapsulada image = gtk.Image()

image.set_from_file ("fall_wallpaper_10.jpg")

image.show()
# Conteiner da imagem scrolled_window = gtk.ScrolledWindow(hadjustment, vadjustment)

scrolled_window.set_policy (gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

scrolled_window.add_with_viewport(image)

scrolled_window.show()

# Acrescenta todos os elementos ao VBox vbox.pack_start (hlabel, False, False, 2)

vbox.pack_start (hscale, False, False, 2)

vbox.pack_start (vlabel, False, False, 2)

vbox.pack_start (vscale, False, False, 2)

vbox.pack_start (scrolled_window, True, True, 2)

# E adiciona o HBox com os conteúdos do botão self.janela.add (vbox)

# Exibe-os vbox.show()

# Exibe a janela self.janela.show ()

defmain (self):

gtk.main()

if __name__ == "__main__":

janela = Janela()

janela.main(
Screenshot:

Até a próxima lição!

Lição 5 - Widgets miscelâneas 2

Iremos nesta lição continuar a exploração pelas widgets do GTK+. Todas estas são vistas com bastante freqüência.
Barras de progresso

Todo usuário as conhece; são usadas para representar o processo de uma operação. Como tudo no GTK+, são fáceis de se criar
e manipular:

progressbar = gtk.ProgressBar(adjustment=None)

O parâmetro adjustment (opcional) pode receber um adjustment criado previamente. Reveja a lição anterior se necessário.

Para alterar o valor exibido pela barra de status, usa-se

progressbar.set_fraction(fraction)

onde fraction é um número entre 0 e 1, representando a percentagem da barra que deverá estar preenchida.

É também possível que o preenchimento ocorra da direita para esquerda (ou outros), em vez de ser da esquerda para a direita:

progressgar.set_orientation(orientation)

orientation pode assumir um dos seguintes valores:

• PROGRESS_LEFT_TO_RIGHT: da esquerda para a direita


• PROGRESS_RIGHT_TO_LEFT: da direita para a esquerda
• PROGRESS_BOTTOM_TO_TOP: de baixo para cima
• PROGRESS_TOP_TO_BOTTOM: de cima para baixo

Além de poder exibir uma fração, a barra pode também indicar que um processo está ocorrendo sem percisar o quanto da
operação foi concluído. Para isso, usa-se pulse:

progressbar.pulse()

Isto exibe uma barra oscilante. E para configurar o tamanho desta barra, usa-se:

progressbar.set_pulse_step (fraction)

Onde fraction novamente é um valor entre 0 e 1.

Para configurar e obter um texto a ser exibido na barra, temos os seguintes comandos:

progressbar.set_text (text)
text = progressbar.get_text ()

O widget Dialog é também conhecido como pop-up por alguns. Consiste em uma janela com alguns elementos empacotados (um
vbox (chamado vbox) para conteúdo e um hbox (chamado action_area) para botões e ações que o usuário possa realizar). Sua
criação é bastante simples:

dialog = gtk.Dialog(title=None, parent=None, flags=0, buttons=None)

Onde title é o título do Dialog, parent é a janela principal da aplicação e flags setam as várias opções de criação, dentre elas:

• DIALOG_MODAL - faz com que o usuário não possa manipular a janela principal, apenas a que foi criada
• DIALOG_DESTROY_WITH_PARENT - força que o Dialog seja destruído quando sua janela principal for fechada
• DIALOG_NO_SEPARATOR - omite o separador enter vbox e action_area

Para adicionar elementos ao Dialog basta empacotar usando pack_start() ou pack_end() no vbox ou action_area do Dialog. Por
exemplo:

dialog.action_area.pack_start(button, True, True, 0)


dialog.vbox.pack_start(label, True, True, 0)

Podem ser manipulados como se fossem janelas (isto é, callbacks para "destroy" funcionarão normalmente, por exemplo).
São widgets relativamente simples que exibem uma mensagem por vez. Servem para auxiliar o usuário na interação com um
programa; por exemplo, quando sobrepor o mouse sobre um ícone a barra de status pode comunicar a funcionalidade do botão.
Ou então informar sobre o progresso de um processo.

Para que permita que várias partes da aplicação utilizem a mesma barra de status, tem-se o que se chama de identificadores de
contexto, que identificam os diferentes "usuários". Ela também tem uma pilha que assegura que a mensagem a ser exibida
sempre será a que está no topo da pilha. (Ou seja, seu funcionamento é LIFO, last in first out).

Para criar uma barra de status:


statusbar = gtk.Statusbar()

Para requisitar-se um identificador de contexto, usa-se a seguinte função, que recebe também uma breve descrição do contexto:

context_id = statusbar.get_context_id (description)

Para inserir uma mensagem, deve-se especificar o id do contexto bem como o texto a ser exibido:

message_id = statusbar.push (context_id, message)

A remoção da última mensagem adicionada naquele contexto é feita assim:

statusbar.pop (context_id)

E a remoção de uma mensagem específica:

statusbar.remove (context_id, message_id)

Lembre-se que a mensagem a ser exibida sempre será a última que foi adicionada (através de push). Como se pode perceber,
cada parte do programa pode interagir com a barra de status de forma independente, já que terá seu próprio context_id.

Como de praxe, terminaremos esta lição de widgets com um exemplo sobre o que foi aprendido.

Por motivos didáticos foi usado um timeout, tópico que não será visto neste curso, para a atualização automatizada da barra de
progresso. No entanto basta saber que timer = gobject.timeout_add(interval, function, ...) irá executar a cada interval
milisegundos a função function. Para que se cancele a execução de um timeout, usa-se gobject.source_remove (timer).

Ao código, misc2.py:

#!/usr/bin/env python# -*- coding: latin-1 -*-import pygtk import gtk import gobject

defprogress_timeout (pbobj):

# Cria valor (valor atual + 1%) valor = pbobj.progressbar.get_fraction() + 0.01

if valor > 1.0:

# Atingimos 100%, fechar popup pbobj.dialog.destroy()

# Ao retornar "False" garantimos que progress_timeout cessará de ser chamadoreturn False

# Atualiza valor da barra de progresso pbobj.progressbar.set_fraction(valor)

# Returna True para que o callback continue sendo executado.return True

classJanela:

defdestroy_popup (self, widget, context_id):

# Fechamento do popup self.statusbar.pop(context_id)

gobject.source_remove (self.timer)

defbotao_popup (self, widget, dialog):

# Aborta operação do popup dialog.destroy()

defpopup (self, data):

# Criação da janela pop-up (perceba a referência à janela que a criou) self.dialog = gtk.Dialog ("Processando...", self.janela,
gtk.DIALOG_MODAL)
# Adiciona-se um botão ao "action_area" (area inferior do pop-up) button = gtk.Button ("Abortar!")

button.connect ("clicked", self.botao_popup, self.dialog)

button.show()

self.dialog.action_area.pack_start (button, True, True, 5)

# Adiciona-se uma barra de progresso ao "vbox" (area superior do pop-up) self.progressbar = gtk.ProgressBar ()

self.progressbar.set_text ("Por favor aguarde...")

self.progressbar.show()

self.dialog.vbox.pack_start (self.progressbar, True, True, 5)

# Cria um timeout que atuailza periodicamente o status da barra de progresso self.timer = gobject.timeout_add (100,
progress_timeout, self)

# Atualiza a mensagem da barra de status na janela principal para indicar atividade context_id = self.statusbar.get_context_id
("popup")

message_id = self.statusbar.push (context_id, "Processando...")

# Associa o fechamento da janela a dsetroy_popup# (para remover a mensagem da barra de status) self.dialog.connect
("destroy", self.destroy_popup, context_id)

# Exibe o pop-up self.dialog.show()

def__init__ (self):

# Primeiro criamos uma janela do tipo WINDOW_TOPLEVEL. self.janela = gtk.Window (gtk.WINDOW_TOPLEVEL)

# Ajustamos alguns parâmetros referentes à janela: self.janela.set_border_width (10)

self.janela.set_title (u"Widgets miscelâneos")

self.janela.resize (200, 80)

# Assegura-se que a janela será fechada corretamente.# (Lembre-se de funções lambda em Python!)
self.janela.connect("destroy", lambda wid: gtk.main_quit())

self.janela.connect("delete_event", lambda a1,a2:gtk.main_quit())

# Conteiner de todos os elementos vbox = gtk.VBox (False, 2)

# Cria o botão que iniciará a ação button = gtk.Button (u"Faça algo!")

button.connect ("clicked", self.popup)

button.show()

# Cria a barra de status e adiciona uma mensagem inicial self.statusbar = gtk.Statusbar()

context_id = self.statusbar.get_context_id ("main")

message_id = self.statusbar.push (context_id, "Em standby.")


self.statusbar.show()

# Insere os elementos recém-criados no vbox vbox.pack_start (button, True, True, 2)

vbox.pack_end (self.statusbar, False, False, 0)

# E adiciona o HBox com os conteúdos do botão self.janela.add (vbox)

# Exibe-os vbox.show()

# Exibe a janela self.janela.show ()

defmain (self):

gtk.main()

if __name__ == "__main__":

janela = Janela()

janela.main()
Screenshot do programa em execução:

Lição 6 - Widgets miscelâneas 3

Em GTK+ existem várias formas possíveis de se criar menus. Neste curso iremos ver a forma mais manual, por motivos
didáticos. Os outros métodos abstraem parte do funcionamento o que acaba sendo prejudicial para o aprendizado.

São 3 os widgets usados para se fazer uma barra de menus e submenus:

• o item de menu, que o usuário clica para realizar a ação solicitada (por exemplo "Fechar")
• o menu, que atua como contêiner para os itens de menu, e
• a barra de menus, que serve de contêiner para cada um dos menus.
Uma abstração do termo item de menu deve ser feita, já que seu widget pode ser usado tanto para criar os itens de menu que
efetivamente realizam a ação solicitada pelo usuário (por exemplo "Novo", "Recortar", "Colar"), quanto para os elementos na
barra de menus (por exemplo "Arquivo", "Editar").

Começando pelo topo, criaremos a barra de menus:

menu_bar = gtk.MenuBar()

Dispensando maiores explicações, esta função cria a barra de menus, que poderá subseqüentemente ser adicionada a outro
contêiner.

menu = gtk.Menu()

Ests função retorna uma referência para um novo menu. Não é necessário chamar a função show(), pois serve apenas de
contêiner para os itens de menu.

menu_item = gtk.MenuItem(label=None)

Finalmente, o item de menu. Este recebe um rótulo (label), que será interpretado por caracteres mnemônicos precedidos de "_".
É necessário que se chame a função show() pra que seja exibido. Não confunda item de menu com menu! O primeiro é o botão
associado a uma ação, e o segundo é um contêiner para itens de menu.

A adição de um item de menu ao menu é feita através do comando append:

menu.append(menu_item)

E, finalmente, a associação de ações aos itens de menu é feita de forma convencional:

menu_item.connect_object ("activate", menuitem_response, "menu_action")

OK, temos o menu pronto. Precisa-se de uma barra de menus:

menu_bar = gtk.MenuBar()
widget.add (menu_bar)
menu_bar.show()

No entanto, lembre-se que o menu em si não pode ser exibido; a exibição do mesmo será feita através de um item de menu,
que será então adicionado à barra de menus:

menu_item_arquivo = gtk.MenuItem("Arquivo")
menu_item_arquivo.show()
menu_item_arquivo.set_submenu(menu)

Caso se queira que o item fique alinhado à direita, podemos usar o seguinte comando antes de adicioná-lo à barra de menus:

menu_item.set_right_justified (right_justified)

Finalmente, o adicionamos à barra de menus, finalizando a construção:

menu_bar.append (menu_item_arquivo)

Afinal, não foi tão difícil quanto possa parecer! Mas agora que você já entende os elementos de construção do menu, caso
deseje automatizar este procedimento, é possívei tanto escrever funções auxiliares ou usar as formas embutidas no GTK+:
ItemFactory ou UIManager. Desde PyGTK 2.4, o uso do ItemFactory está depreciado, portanto deve-se usar o UIManager, que
constrói o menu a partir de uma estrutura XML

Um elemento crucial de interfaces deixado de fora até o momento é o campo onde o usuário pode entrar com conteúdo livre
(texto). Em GTK+ um tal widget é o Entry. Este permite criar um campo simples, de apenas uma linha.
A sintaxe de criação é a seguinte:

entry = gtk.Entry (max=0)

onde max é o limite de caracteres permitido, e o valor 0 indica a ausência da limitação. Sua alteração é possível após a criação:

entry.set_max_length (max)

Da mesma forma é possível alterar o conteúdo (texto):

entry.set_text (text)

(Como a classe Entry é derivada da classe Editable, aquela suporta algumas funções tais como insert_text; a lista completa pode
ser visualizada em http://www.pygtk.org/docs/pygtk/class-gtkeditable.html).

entry.set_editable(editable)
entry.set_visibility(visible)

Estes comandos permitem, respectivamente, habilitar e desabiiltar a edição de seu conteúdo por parte do usuário (onde editable
pode ser True ou False), e permitir ou não a visualização do conteúdo sendo digitado. Isto pode ser útil em campos de senhas.

Este tipo de botão pode ser usado pelo usuário para se escolher entre uma faixa de valores numéricos. Seu funcionamento rege
em torno dos Adjustments; reveja a lição caso seja necessário.

A criação do spin button é feita assim:

spin_button = gtk.SpinButton(adjustment=None, climb_rate=0.0, digits=0)

O adjustment será automaticamente criado caso seja omitido, e é o que controla a faixa de valores do widget. O climb rate
indica a quantidade de aceleração que o botão tem ao ser pressionado (variando entre 0.0 e 1.0), e digits é a quantidade de
casas decimais que deve ser exibida.

É possível também alterar esses valores:

spin_button.configure (adjustment, climb_rate, digits)

que obedece à mesma sintaxe descrita acima.

Da mesma forma é possível alterar apenas outros parâmetros:

spin_button.set_adjustment (adjustment)
spin_button.set_digits (digits)
spin_button.set_value (value)

Ou obter o valor do spin button:

float_value = spin_button.get_value()
int_value = spin_button.get_value_as_int()

A alteração do valor também pode ser feita de forma relativa através da função spin:

spin_button.spin (direction, increment)

onde direction pode assumir um dos seguintes valores:

• SPIN_STEP_FORWARD - Aumenta o valor do spin button de acordo com o valor increment ou page_increment (do
Adjustment) caso increment seja igual a 0.
• SPIN_STEP_BACKWARD - Diminui o valor do spin button de acordo com o valor increment ou page_increment (do
Adjustment) caso increment seja igual a 0.
• SPIN_PAGE_FORWARD - Aumenta o valor do spin button de acordo com o valor increment.
• SPIN_PAGE_BACKWARD - Diminui o valor do spin button de acordo com o valor increment.
• SPIN_HOME - Ajusta o valor para o mínimo do Adjustment.
• SPIN_END - Ajusta o valor para o máximo do Adjustment.
• SPIN_USER_DEFINED - Altera o valor pela quantidade especificada.

Algumas funções podem controlar a aparência e o comportamento do botão de forma mais detalhada:

spin_button.set_numeric (numeric)

Se numeric for True, isto garantirá que o usuário pode digitar apenas números no spin button; caso contrário outros caracteres
poderão ser digitados.

spin_button.set_wrap (wrap)

Já este comando faz com que, caso wrap seja True, o botão retorne ao valor mínimo quando o usuário atingir o valor máximo e
vice-versa.

spin_button.set_snap_to_ticks (snap_to_ticks)

Esta função faz com que valores "quebrados" sejam arredondados para seus equivalentes mais próximos explicitados pelo
Adjustment.

spin_button.set_update_policy (policy)

onde policy pode ser UPDATE_ALWAYS ou UPDATE_IF_VALID, onde o primeiro atualiza o valor mesmo que este seja inválido
(após uma alteração), e o segundo ignora erros enquanto convertendo para valor numérico.

Este é um dos widgets mais visto nos programas, por isso seria extremamente entediante se cada desenvolvedor tivesse de
programar tal funcionalidade, sem contar que provavelmente seriam inconsistentes.

Com isso em mente, os desenvolvedores do GTK+ incluiram isso como uma widget fácil de se usar. Para criá-la:

filesel = gtk.FileSelection(title=None)

Para alterar o endereço sendo exibido, temos:

filesel.set_filename (filename)

O que irá atualizar a janela de maneira correspondente.

Para obter o arquivo selecionado:


filename = filesel.get_filename()

Como são várias as widgets que compõem o file selection dialog, é possível manipular essas widgets "internas" normalmente.
Elas seguem o seguinte padrão de nomes:

filesel.dir_list
filesel.file_list
filesel.selection_entry
filesel.selection_text
filesel.main_vbox
filesel.ok_button
filesel.cancel_button
filesel.help_button
filesel.history_pulldown
filesel.history_menu
filesel.fileop_dialog
filesel.fileop_entry
filesel.fileop_file
filesel.fileop_c_dir
filesel.fileop_del_file
filesel.fileop_ren_file
filesel.button_area
filesel.action_area

Em particular, é útil manipular os sinais do ok_button, cancel_button e help_button para atribuir funcionalides aos mesmos.

Ficará como exercício ao leitor experimentar com os widgets apresentados nesta lição, já que o funcionamento destes é
praticamente idêntico aos apresentados anteriormente.

Lição 7 - Controle avançado de layout

O widget de alinhamento (Alignment) permite que se adicione um widget em uma posição e tamanho relativo ao widget de
alinhamento. Por exemplo, pode ser usado para se centralizar um botão na tela.

Existem apenas dois comandos a serem aprendidos:

alignment = gtk.Alignment (xalign=0.0, yalign=0.0, xscale=0.0, yscale=0.0)


align.set (xalign, yalign, xscale, yscale)

Como é de se esperar, o gtk.Alignment cria uma widget de alinhamento com os parâmetros especificados. Os valores são em
ponto-flutuante, e devem variar entre 0.0 e 1.0. O xalign e yalign ajustam a posição do widget no Alignment. Estas propriedades
especificam a fração de espaço vazio que deve ser adicionado ao topo (yalign) ou à esquerda (xalign) do widget inserido.

Os outros dois parâmetros (xscale e yscale) definem a quantidade de espaço vazio que deve ser absorvido pela widget: 0.0 não
absorve nenhum espaço, e 1.0 absorve todo o espaço vazio disponível. Naturalmente se ambos xscale e yscale forem iguais a
1.0, então o uso do widget de alinhamento perde seu sentido, já que todo espaço vazio será absorvido.

Para adicionar um (e apenas um) widget ao alinhamento, usa-se alignment.add(widget).

Screenshot para transmitir a idéia:

O contêiner fixo permite que se posicione widgets em uma posição, ..., fixa. Esta posição é relativa à ponta superior esquerda.
Além disso, a posição dos widgets pode ser alterada dinamicamente.

Novamente são poucos os comandos que precisam ser aprendidos:


fixed = gtk.Fixed()
fixed.put (widget, x, y)
fixed.move (widget, x, y)

O primeiro comando cria o widget (fixed) ao qual poderão ser adicionados outros (widget). O segundo adiciona a widget
desejada (widget) ao widget fixo (fixed) na posição x e y. O terceiro meramente muda a widget de posição.

É possível adicionar vários widgets a um layout do tipo fixo.

Veja o seguinte exemplo:

Estes devem ser usados com cautela, já que algumas configurações locais (como tamanho de fontes) serão ignorados, como a
posição é absoluta.
O contêiner Layout é bastante similar ao último visto (Fixed), com a exceção de que ele implementa uma área infinita (ou
melhor dizendo, até 2^32 pixels, devido a uma restrição do X). Também se assemelha a um layout Fixed adicionado a uma
ScrolledWindow, mas sem as barras de rolagem. É basicamente a mesma idéia implementada de forma um pouco diferente.

A criação é feita usando

layout = gtk.Layout (hadjustment=None, vadjustment=None)

Como se pode perceber, é possível especificar objetos do tipo Adjustment que o widget Layout irá usar para barra de rolagem.
Omiti-los significa que novos adjustments serão criados.

Para respectivamente adicionar e mover widgets, usa-se

layout.put(widget, x, y)
layout.put(widget, x, y)

O tamanho do contêiner Layout pode ser ajustado e obtido usando estes 2 comandos:

layout.set_size (width, height)


size = layout.get_size()

Finalmente, para obter e manipular os Adjustments

hadj = layout.get_hadjustment()
vadj = layout.get_vadjustment()
layout.set_hadjustment(adjustment)
layout.set_vadjustment(adjustment)

Perceba que este contêiner não inclui a barra de rolagem, sendo necessário adicioná-las manualmente.

Veja o seguinte exemplo:


Frames normalmente são usados para agrupar widgets de forma clara e objetiva. Ao contrário dos últimos widgets de
agrupamento, este agrupa de forma visível ao usuário. Pode ser usado, por exemplo, para separar seções em um grande
formulário, ou para separar opções de partes distintas de um programa.

Criá-los é simples:

frame = gtk.Frame (label=None)

O label é a descrição (visível) do agrupamento, que por padrão estará no canto superior esquerdo. Pode também ser omitido. É
possível também alterá-lo, através do comando

frame.set_label(label)

Para mudar a posição do label, usa-se a função

frame.set_label_align (xalign, yalign)

onde o parâmetro xalign pode variar entre 0.0 (esquerda) e 1.0 (direita). Atualmente o yalign não é usado.

A adição de uma widget ao frame é feita usando-se frame.add (widget).

Exemplo:

Muitas vezes, por exemplo em um programa de e-mail, se deseja dividir uma área em 2 partes tal que o usuário possa controlar
o tamanho de cada uma dessas áreas. O GTK+ permite que se faça isso diretamente através de 2 funções:

hpane = gtk.HPaned()
vpane = gtk.VPaned()

A HPane() criará uma divisória horizontal (ou seja, uma área superior e outra inferior), o VPane() fará o seu equivalente vertical.

Para adicionar um elemento a cada uma das áreas, temos os seguintes comandos:

paned.add1(child)
paned.add2(child)

O add1 adicionará o widget desejado ao painel superior (ou esquerdo), enquanto o add2 o adicionará ao painel inferior (ou
direito).
Lição 8 - Progredindo com PyGTK

E como já deve ter sido possível perceber, o dicionário dic associa cada handler a uma função. A função signal_autoconnect
faz a associação automaticamente e de uma só vez.

Falso.

Verdadeiro
.

Infelizmente o curso não irá se aprofundar mais do que isso em Glade, ficando isso a cargo do leitor. Informações sobre Glade
podem ser encontradas na Web; a página do próprio Glade é um bom ponto de partida: http://glade.gnome.org/

E com isso concluímos o curso. Boa parte da matéria foi vista, mas recomenda-se ao aluno que nunca pare de aprender novas
tecnologias e aprofundar-se nas existentes; busque cursos, sites, leia, mas não fique parado!

Espero que tenham gostado!