Introdução
Pygtk é uma camada Python construída sobre o Gtk. Gtk nada mais é que o Gimp Toolkit, biblioteca utilizada pelo GNOME na criação de interfaces.
Esse tutorial foi construído com base no Manual de Referencia do Gtk3 e no Python GTK+ 3 Tutorial.
Requisitos
- Python 2.7.6 padrão (no Linux), em breve a versão 3 o substituirá.
- Gtk3
- Gdk
- Sqlite3
A maioria das distribuições Linux já contam com o Python e o Gtk instalados por padrão. Para verificar se sua distribuição conta com os pacotes necessários abra o terminal e digite:
python –version
Gtk
Para verificar se há bibliotecas Gtk instaladas em uma distribuição derivada do Debian, digite:
dpkg -l libgtk2.0-0 libgtk-3-0
Deve retornar algo do tipo:
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Nome Versão Arquitectura Descrição
+++-===============================-====================-====================-=======
ii libgtk-3-0:amd64 3.14.8-0ubuntu1
14.0 amd64 GTK+ graphical user interface library
rc libgtk-3-0:i386 3.14.8-0ubuntu114.0 i386 GTK+ graphical user interface library
ii libgtk2.0-0:amd64 2.24.23-0ubuntu1.1 amd64 GTK+ graphical user interface library
ii libgtk2.0-0:i386 2.24.23-0ubuntu1.1 i386 GTK+ graphical user interface library
Se você estiver utilizando uma distribuição derivada do Red Hat, digite:
yum list installed gtk3-devel gtk2-devel
O retorno a seguir mostra que os pacotes estão corretamente instalados:
Plugins carregados: auto-update-debuginfo, langpacks
Pacotes instalados
gtk2-devel.x86_64 2.24.26-1.fc21 installed
gtk3-devel.x86_64 3.14.8-2.fc21 installed
Usuários de Mac OSX podem conferir este post.
Usuários Windows precisam baixar o interpretador Python aqui e o utilitário de instalação do PyGTK aqui.
Daqui em diante será mostrando o exemplo utilizando PyGtk. Logo abaixo é possível ver a importação das bibliotecas necessárias para construir a aplicação. Estas são as mesmas bibliotecas que foram verificadas anteriormente:
Conhecendo Gtk.Window
A princípio criei uma classe Janela que herda de Gtk.Window, essa será a janela principal. Logo em seguida, define-se o método construtor e todos os atributos da janela principal, como o título da janela, o tamanho padrão, se a tela vai ser redimensionada ou não, cor de fundo e etc. Veja no código a seguir.
No código acima, é instanciada a classe Gtk.Window e configurado os seus atributos, sendo eles o título da janela, tamanho da janela em pixels (600x600), configuração para não redimensionar a janela, e a cor de fundo da janela. O método modify_bg, que altera a cor da janela, recebe dois argumentos: um tipo de estado do gtk (StateType) e o color_parse com uma cor em Hexadecimal. Os estados possíveis que o modify_bg pode receber são: NORMAL, FOCUSED, ACTIVE, INCONSISTENT, INSENSITIVE, PRELIGHT e SELECTED, lembre-se, todos em maiúsculos. O que cada um estado representa? veja aqui.
Atenção, objetos do tipo Window só aceitam um objeto por vez. Para poder utilizar múltiplos objetos por vez é necessário utilizar objetos containers dentro da janela. Começaremos com um container grid, que agrupará outros widgets.
Gtk.Grid
A Grid é um elemento do tipo container que contempla vários widgets como entradas de texto, labels, botões e toda parte que se pode interagir com a aplicação. Você deve imaginar uma grid exatamente como uma tabela. Aqui são adicionadas duas grids. Dentro de uma grid, vai um elemento box1 que é um Gtk.Box que também é um objeto container. É completamente necessário adicionar a nova box de fato na grid utilizando o grid.attach. O grid.attach recebe 5 parâmetros, sendo a referência do objeto a ser adicionado (self), left, top, width e height.
Label
Labelinit é um objeto do tipo Label que é utilizado para textos, e que será o título da aplicação. Um dos mais interessantes métodos da classe label é o set_markup, pois ele recebe como argumento uma string formatada em pango markup language. Quer conhecer mais? Então clique aqui.
Mas lembre-se, apesar de ter uma sintaxe muito parecida, Pango não é HTML, portanto, nem todas as tags que você por funcionarão.
Box
A inserção de qualquer objeto em um elemento do tipo Box, se dá por dois comandos: Box.pack_start para adicionar objetos no início da box e Box.pack_end que obviamente adiciona objetos no fim da box. Os parâmetros informam se ele será expansível ou não, se terá preenchimento e espaço entre os objetos. Por fim, crio um novo objeto do tipo Grid, chamada de grid2 e passo a quantidade de espaço entre duas colunas consecutivas, espaço da coluna e espaço da linha. Confira Linha 34 do código anterior.
Com toda a estrutura da janela criada, vamos aos objetos!
Widgets
Widgets são objetos comuns de uma interface, como campo de entrada, textos, botões, caixa de seleção e etc. Eles obrigatoriamente devem ficar contidos em objetos containers, como Grids ou Box. O primeiro objeto é o label do nome, o set_halign representa o alinhamento horizontal do objeto em relação a grid ou box em que esse objeto está, da mesma forma temos set_valign para o alinhamento vertical. Eles recebem como parâmetro um objeto do tipo Gtk.Align, e os tipos são: BASELINE, CENTER, FILL, START. Dúvidas sobre os tipos? Veja mais aqui.
Em seguida, adicionamos na grid1 com left=0, top=1, width=1 e height=1. Objetos do tipo Gtk.Entry (Linha 39) são altamente configuráveis, no exemplo fi configurado o max_length para 150, que é o maior quantidade de caracteres que o campo pode receber, e o tamanho do campo width_chars em caracteres(30), note que um é completamente diferente do outro. Por fim, adicionei o objeto na grid2 e criei uma conexão.
Conexões
Conexão é, a grosso modo, a ligação do estado do objeto com um método. No exemplo, é criado uma conexão do estado “changed” com um método chamado “on_entry_nome_changed” , até então não criado ainda. Mas o que ela faz? Ela é chamada toda vez que o estado da entry_nome for mudada.
O que se segue agora é a repetição do código acima com apenas algumas modificações. Vamos criar um label e um entry para cada entrada que o usuário tiver que digitar. Note que, o objeto label é o texto que fica ao lado da área para o usuário digitar. E o objeto entry é justamente o campo.
A única diferença está no objeto entry_tel que chama o set_text para demonstrar como deve ser a entrada do telefone, e logo abaixo é configurada a cor cinza claro via Gdk._color_parse. (Linhas 63 e 64)
O mesmo acontece com as próximas entradas Email e Data de Nascimento.
Gtk.ComboBoxText
O Gtk.ComboBoxText é um meio de entrada de dados que utiliza uma lista já criada e recebe três parâmetros, um inteiro informando a ordem, um id e o texto.
Gtk.Button
Criei um objeto chamado commit do tipo Gtk.Button (Linha 110). Este objeto recebe como parâmetros: um label, um alinhamento, o posicionamento na grid, o tamanho do botão, e uma conexão usando o sinal “clicked”(com outro método que não está criado ainda).
Adicionando objetos containers no container principal
Por fim, vamos pegar todas as grids e box que criamos no meio do caminho e vamos amarrá-las à grid principal chamada grid_total (Linhas 121 e 122 do código abaixo).
Métodos
Vamos fazer dois métodos para o funcionamento do formulário. O primeiro método será on_entry_nome_changed para auxiliar na entrada do nome do usuário. A utilização deste método se deve ao fato dele colocar o nome em maiúsculo em tempo de execução. Funciona da seguinte maneira: O usuário coloca o nome e em tempo de execução, o método transforma os caracteres para maiúsculo, por isso é usado o sinal “changed”, pois a cada carácter novo o método precisa torná-lo maiúsculo. Então ele pega o texto via get_text e faz o upper, que torna-o maiúsculo e devolve o texto por outra função set_text. Confira no código abaixo.
O segundo método é o do botão de cadastro. Este é o momento de salvar os dados no banco.
Ele pega todos as entradas de todos os campos via get_text ou via get_active_text (para objetos ComboBoxText). Se não forem nulos, ele os envia para a função que de fato faz commit no banco de dados. Se todas as entradas forem informadas, o método commit_dados é chamado. Caso um dos campos for nulo ele executa o comando pass e não envia nada ao sqlite (Linhas 141 à 144 do código abaixo).
A função “commit_dados” recebe os parâmetros, cria uma conexão sqlite3 com um arquivo de banco de dados. A segunda linha do código é necessária para o sqlite possa processar texto do tipo 8-bits. É preciso também criar um cursor, pois é nele que vamos executar os comandos sql.
Passo todos os parâmetros em apenas dois comandos sql (Linhas 151 e 152), sendo que o primeiro verifica se o banco de dados já existe. Se não existir, ele cria o banco e o modelo, setando os tipos de dados e os nomes dos campos. O segundo insere os dados nos campos. Os dados são pegos pelos argumentos da função principal *args e são passados como símbolos(?) para cada campo inserido. Lembre-se que a quantidade de “?” tem que ser a mesma quantidade de parâmetros contido em *args. No final, executo uma função da conexão chamada commit que salva os dados no banco.
Cuidado para não confundir a função commit_dados do botão com a função do sqlite commit.
A última coisa a fazer é iniciar a aplicação…
Crio um objeto do tipo Janela(), que é a nossa janela principal. Utilizo o connect para criar uma conexão entre a janela principal e o sinal “delete-event” (que é o sinal de fechar a janela). O comando show_all exibe todos os widgets ligados a janela, seja grid, box, entry, comboboxtext, entre outros.
E por fim Gtk.main() inicia o gtk executando tudo.
Se você seguiu passo a passo a criação da aplicação essa deve ser a aparência final.
Espero que você tenha gostado do mini-tutorial, e principalmente tenha aprendido algo, pois a intenção é justamente passar o conhecimento para frente! O código completo da aplicação você pode acessar clicando aqui.
Em caso de dúvidas deixe um comentário.
Obrigado, e até mais!