python gtk

72
Python-GTK 23 de maio de 2007

Upload: tiago

Post on 16-Apr-2017

108 views

Category:

Education


1 download

TRANSCRIPT

Page 1: Python gtk

Python-GTK23 de maio de 2007

Page 2: Python gtk

Sumário

I Sobre essa Apostila 3

II Informações Básicas 5

III Python-GTK 10

1 O que é o Curso 11

2 Plano de ensino 122.1 Objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.2 Público Alvo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.3 Pré-requisitos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.4 Descrição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.5 Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.6 Cronograma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.7 Programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.8 Avaliação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.9 Bibliografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 Lição 1 - Apresentando PyGTK 153.1 Um breve histórico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2 Primeiros passos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.3 Conferindo a instalação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

4 Lição 2 - Apresentando Widgets, Signals e Callbacks 194.1 Conceitos básicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194.2 Um exemplo prático . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

5 Lição 3 - Widgets elementares 245.1 Empacotando widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245.2 O widget do botão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

6 Lição 4 - Widgets miscelâneas 1 346.1 Adjustments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346.2 Widgets de faixa de valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356.3 Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376.4 Áreas com barras de rolagem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386.5 Exemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

1

Page 3: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

7 Lição 5 - Widgets miscelâneas 2 437.1 Barras de progresso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437.2 Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447.3 Barras de status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457.4 Exemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

8 Lição 6 - Widgets miscelâneas 3 518.1 Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518.2 Entrada de texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538.3 Spin buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548.4 Diálogo de seleção de arquivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

9 Lição 7 - Controle avançado de layout 589.1 Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589.2 Contêiner Fixed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599.3 Contêiner layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609.4 Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619.5 Paned Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

10 Lição 8 - Progredindo com PyGTK 6410.1 Progredindo com PyGTK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6410.2 Matéria extra: Criando interfaces gráficas usando PyGTK e Glade . . . . . . . . . . 6410.3 Despedidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

2

Page 4: Python gtk

Parte I

Sobre essa Apostila

3

Page 5: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Conteúdo

O conteúdo dessa apostila é fruto da compilação de diversos materiais livres publicados na in-ternet, disponíveis em diversos sites ou originalmente produzido no CDTC em http://www.cdtc.org.br.

O formato original deste material bem como sua atualização está disponível dentro da licençaGNU Free Documentation License, cujo teor integral encontra-se aqui reproduzido na seção demesmo nome, tendo inclusive uma versão traduzida (não oficial).

A revisão e alteração vem sendo realizada pelo CDTC ([email protected]) desde outubrode 2006. Críticas e sugestões construtivas são bem-vindas a qualquer tempo.

Autores

A autoria deste é de responsabilidade de Pedro Guerra Brandão.

O texto original faz parte do projeto Centro de Difusão de Tecnologia e Conhecimento, quevem sendo realizado pelo ITI (Instituto Nacional de Tecnologia da Informação) em conjunto comoutros parceiros institucionais, atuando em conjunto com as universidades federais brasileirasque tem produzido e utilizado Software Livre, apoiando inclusive a comunidade Free Softwarejunto a outras entidades no país.

Informações adicionais podem ser obtidas através do email [email protected], ou dahome page da entidade, através da URL http://www.cdtc.org.br.

Garantias

O material contido nesta apostila é isento de garantias e o seu uso é de inteira responsabi-lidade do usuário/leitor. Os autores, bem como o ITI e seus parceiros, não se responsabilizamdireta ou indiretamente por qualquer prejuízo oriundo da utilização do material aqui contido.

Licença

Copyright ©2006, Instituto Nacional de Tecnologia da Informação ([email protected]) .

Permission is granted to copy, distribute and/or modify this document under the termsof the GNU Free Documentation License, Version 1.1 or any later version published bythe Free Software Foundation; with the Invariant Chapter being SOBRE ESSA APOS-TILA. A copy of the license is included in the section entitled GNU Free DocumentationLicense.

4

Page 6: Python gtk

Parte II

Informações Básicas

5

Page 7: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Sobre o CDTC

Objetivo Geral

O Projeto CDTC visa a promoção e o desenvolvimento de ações que incentivem a dissemina-ção de soluções que utilizem padrões abertos e não proprietários de tecnologia, em proveito dodesenvolvimento social, cultural, político, tecnológico e econômico da sociedade brasileira.

Objetivo Específico

Auxiliar o Governo Federal na implantação do plano nacional de software não-proprietário ede código fonte aberto, identificando e mobilizando grupos de formadores de opinião dentre osservidores públicos e agentes políticos da União Federal, estimulando e incentivando o mercadonacional a adotar novos modelos de negócio da tecnologia da informação e de novos negóciosde comunicação com base em software não-proprietário e de código fonte aberto, oferecendotreinamento específico para técnicos, profissionais de suporte e funcionários públicos usuários,criando grupos de funcionários públicos que irão treinar outros funcionários públicos e atuar comoincentivadores e defensores de produtos de software não proprietários e código fonte aberto, ofe-recendo conteúdo técnico on-line para serviços de suporte, ferramentas para desenvolvimento deprodutos de software não proprietários e de seu código fonte livre, articulando redes de terceiros(dentro e fora do governo) fornecedoras de educação, pesquisa, desenvolvimento e teste de pro-dutos de software livre.

Guia do aluno

Neste guia, você terá reunidas uma série de informações importantes para que você comeceseu curso. São elas:

• Licenças para cópia de material disponível

• Os 10 mandamentos do aluno de Educação a Distância

• Como participar dos foruns e da wikipédia

• Primeiros passos

É muito importante que você entre em contato com TODAS estas informações, seguindo oroteiro acima.

Licença

Copyright ©2006, Instituto Nacional de Tecnologia da Informação ([email protected]).

6

Page 8: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

É dada permissão para copiar, distribuir e/ou modificar este documento sob os termosda Licença de Documentação Livre GNU, Versão 1.1 ou qualquer versão posteriorpúblicada pela Free Software Foundation; com o Capitulo Invariante SOBRE ESSAAPOSTILA. Uma cópia da licença está inclusa na seção entitulada "Licença de Docu-mentação Livre GNU".

Os 10 mandamentos do aluno de educação online

• 1. Acesso à Internet: ter endereço eletrônico, um provedor e um equipamento adequado épré-requisito para a participação nos cursos a distância.

• 2. Habilidade e disposição para operar programas: ter conhecimentos básicos de Informá-tica é necessário para poder executar as tarefas.

• 3. Vontade para aprender colaborativamente: interagir, ser participativo no ensino a distân-cia conta muitos pontos, pois irá colaborar para o processo ensino-aprendizagem pessoal,dos colegas e dos professores.

• 4. Comportamentos compatíveis com a etiqueta: mostrar-se interessado em conhecer seuscolegas de turma respeitando-os e fazendo ser respeitado pelo mesmo.

• 5. Organização pessoal: planejar e organizar tudo é fundamental para facilitar a sua revisãoe a sua recuperação de materiais.

• 6. Vontade para realizar as atividades no tempo correto: anotar todas as suas obrigações erealizá-las em tempo real.

• 7. Curiosidade e abertura para inovações: aceitar novas idéias e inovar sempre.

• 8. Flexibilidade e adaptação: requisitos necessário à mudança tecnológica, aprendizagense descobertas.

• 9. Objetividade em sua comunicação: comunicar-se de forma clara, breve e transparente éponto - chave na comunicação pela Internet.

• 10. Responsabilidade: ser responsável por seu próprio aprendizado. O ambiente virtual nãocontrola a sua dedicação, mas reflete os resultados do seu esforço e da sua colaboração.

Como participar dos fóruns e Wikipédia

Você tem um problema e precisa de ajuda?

Podemos te ajudar de 2 formas:

A primeira é o uso dos fóruns de notícias e de dúvidas gerais que se distinguem pelo uso:

. O fórum de notícias tem por objetivo disponibilizar um meio de acesso rápido a informaçõesque sejam pertinentes ao curso (avisos, notícias). As mensagens postadas nele são enviadas a

7

Page 9: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

todos participantes. Assim, se o monitor ou algum outro participante tiver uma informação queinteresse ao grupo, favor postá-la aqui.Porém, se o que você deseja é resolver alguma dúvida ou discutir algum tópico específico docurso. É recomendado que você faça uso do Forum de dúvidas gerais que lhe dá recursos maisefetivos para esta prática.

. O fórum de dúvidas gerais tem por objetivo disponibilizar um meio fácil, rápido e interativopara solucionar suas dúvidas e trocar experiências. As mensagens postadas nele são enviadasa todos participantes do curso. Assim, fica muito mais fácil obter respostas, já que todos podemajudar.Se você receber uma mensagem com algum tópico que saiba responder, não se preocupe com aformalização ou a gramática. Responda! E não se esqueça de que antes de abrir um novo tópicoé recomendável ver se a sua pergunta já foi feita por outro participante.

A segunda forma se dá pelas Wikis:

. Uma wiki é uma página web que pode ser editada colaborativamente, ou seja, qualquer par-ticipante pode inserir, editar, apagar textos. As versões antigas vão sendo arquivadas e podemser recuperadas a qualquer momento que um dos participantes o desejar. Assim, ela oferece umótimo suporte a processos de aprendizagem colaborativa. A maior wiki na web é o site "Wikipé-dia", uma experiência grandiosa de construção de uma enciclopédia de forma colaborativa, porpessoas de todas as partes do mundo. Acesse-a em português pelos links:

• Página principal da Wiki - http://pt.wikipedia.org/wiki/

Agradecemos antecipadamente a sua colaboração com a aprendizagem do grupo!

Primeiros Passos

Para uma melhor aprendizagem é recomendável que você siga os seguintes passos:

• Ler o Plano de Ensino e entender a que seu curso se dispõe a ensinar;

• Ler a Ambientação do Moodle para aprender a navegar neste ambiente e se utilizar dasferramentas básicas do mesmo;

• Entrar nas lições seguindo a seqüência descrita no Plano de Ensino;

• Qualquer dúvida, reporte ao Fórum de Dúvidas Gerais.

Perfil do Tutor

Segue-se uma descrição do tutor ideal, baseada no feedback de alunos e de tutores.

O tutor ideal é um modelo de excelência: é consistente, justo e profissional nos respectivosvalores e atitudes, incentiva mas é honesto, imparcial, amável, positivo, respeitador, aceita asidéias dos estudantes, é paciente, pessoal, tolerante, apreciativo, compreensivo e pronto a ajudar.

8

Page 10: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

A classificação por um tutor desta natureza proporciona o melhor feedback possível, é crucial, e,para a maior parte dos alunos, constitui o ponto central do processo de aprendizagem.’ Este tutorou instrutor:

• fornece explicações claras acerca do que ele espera, e do estilo de classificação que iráutilizar;

• gosta que lhe façam perguntas adicionais;

• identifica as nossas falhas, mas corrige-as amavelmente’, diz um estudante, ’e explica por-que motivo a classificação foi ou não foi atribuída’;

• tece comentários completos e construtivos, mas de forma agradável (em contraste com umreparo de um estudante: ’os comentários deixam-nos com uma sensação de crítica, deameaça e de nervossismo’)

• dá uma ajuda complementar para encorajar um estudante em dificuldade;

• esclarece pontos que não foram entendidos, ou corretamente aprendidos anteriormente;

• ajuda o estudante a alcançar os seus objetivos;

• é flexível quando necessário;

• mostra um interesse genuíno em motivar os alunos (mesmo os principiantes e, por isso,talvez numa fase menos interessante para o tutor);

• escreve todas as correções de forma legível e com um nível de pormenorização adequado;

• acima de tudo, devolve os trabalhos rapidamente;

9

Page 11: Python gtk

Parte III

Python-GTK

10

Page 12: Python gtk

Capítulo 1

O que é o Curso

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 paraprover uma interface ao Python para acesso ao GTK, possibilitando ao desenvolvedor a criaçãode sistemas com interfaces gráficas riquíssimas.

11

Page 13: Python gtk

Capítulo 2

Plano de ensino

2.1 Objetivo

Habilitar técnicos e programadores a usarem a biblioteca PyGTK, para Python.

2.2 Público Alvo

Técnicos e Programadores que desejem trabalhar com PyGTK.

2.3 Pré-requisitos

Os usuários deverão ser, necessariamente, indicados por empresas públicas e ter certo co-nhecimento da linguagem Python. É recomendável um conhecimento mínimo nos recursos es-pecíficos da linguagem (por exemplo dicionários e tuplas). Noções de orientação a objetos emPython também são recomendáveis.

Não é necessário conhecimento prévio de GTK+.

2.4 Descrição

O curso de Introdução ao Python será realizado na modalidade EAD e utilizará a plataformaMoodle como ferramenta de aprendizagem. Ele é composto de um módulo de aprendizado queserá dado na primeira semana e um módulo de avaliação que será dado na segunda semana. Omaterial didático estará disponível on-line de acordo com as datas pré-estabelecidas no calendá-rio. A versão utilizada para o PyGTK será a 2.10.

2.5 Metodologia

O curso está dividido da seguinte maneira:

12

Page 14: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

2.6 Cronograma

• 1ª Semana - Introdução + Conceitos básicos;

• 2ª Semana - Conceitos avançados.

Todo o material está no formato de livro, e estará disponível ao longo do curso. O livro poderáser acessado quantas vezes forem necessárias. Aconselhamos a leitura de "Ambientação doMoodle", para que você conheça o produto de Ensino a Distância, evitando dificuldades advindasdo "desconhecimento"sobre o mesmo.

Ao final de cada semana do curso será disponibilizada a prova referente ao módulo estudadoanteriormente que também conterá perguntas sobre os textos indicados. Utilize o material decada semana e os exemplos disponibilizados para se preparar para prova.

Os instrutores estarão à sua disposição ao longo de todo curso. Qualquer dúvida deve serdisponibilizada no fórum ou enviada por e-mail. Diariamente os monitores darão respostas e es-clarecimentos.

2.7 Programa

O curso oferecerá o seguinte conteúdo:

Semana 1:

• Visão Geral e Histórico;

• Introdução;

• Um breve exemplo;

• Modificando parâmetros;

• Callbacks;

• Widgets básicos.

Semana 2:

1. Outras widgets;

2. Aperfeiçoando o controle de layout;

3. Automatizando o processo de criação de interfaces.

2.8 Avaliação

Toda a avaliação será feita on-line.Aspectos a serem considerados na avaliação:

• Iniciativa e autonomia no processo de aprendizagem e de produção de conhecimento;

• Capacidade de pesquisa e abordagem criativa na solução dos problemas apresentados.

13

Page 15: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Instrumentos de avaliação:

• Participação ativa nas atividades programadas;

• Avaliação ao final do curso;

• O participante fará várias avaliações referente ao conteúdo do curso. Para a aprovação eobtenção do certificado o participante deverá obter nota final maior ou igual a 6.0 de acordocom a fórmula abaixo:

• Nota Final = ((ML x 7) + (AF x 3)) / 10 = Média aritmética das lições;

• AF = Avaliações.

2.9 Bibliografia

• Site official: http://www.python.org

• Guia: http://www.pygtk.org/pygtk2tutorial/index.html

14

Page 16: Python gtk

Capítulo 3

Lição 1 - Apresentando PyGTK

3.1 Um breve histórico

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

GTK+

O GIMP Toolkit, popularmente conhecido por GTK+, é um dos mais famosos toolkits voltadospara a criação de interfaces gráficas (referidas GUIs daqui em diante). O que, então, justifica aparte GIMP do nome? Originalmente, foi idealizado para servir de base para o editor de imagensGIMP (GNU Image Manipulation Program), mas acabou expandindo muito além.

O GTK+ é um dos pilares do famoso ambiente de janelas GNOME, portanto aplicações base-adas nesta biblioteca podem ser facilmente identificadas pelo visual em comum.

Seus autores incluem Spencer Kimball, Peter Mattis e Josh MacDonald, todos os quais traba-lhavam na Universidade de Berkeley à época de criação do GTK+/GIMP.

15

Page 17: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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

Python

Python é uma linguagem de programação de alto nível orientada a objetos. Seu criador, Guidovan Rossum, a criou em 1991 com o objetivo de enfatizar o esforço do programador sobre o es-forç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 correta-mente, o que conseqüentemente facilita bastante a sua compreensão e padroniza os programascom 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á umavasta quantidade de bibliotecas disponíveis, inclusive distribuídas com o Python. Uma destas,aliás, é o...

16

Page 18: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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, partiremospara um overview geral.

O PyGTK é um conjunto de wrappers (vulgarmente "envoltórios") para a biblioteca GTK+. As-sim como o Python, o PyGTK é software livre, no entanto é distribuído sob a licença LGPL. É deautoria de um dos desenvolvedores do GNOME, James Henstridge, e hoje possui uma equipemaior, 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çõesrodando nos sistemas do projeto One Laptop Per Child. Além disso, algums outros projetos usamo PyGTK, tais como:

• Instalador Anaconda (usado no Fedora);

• Bittorrent (cliente);

• GNOME Sudoku (ótimo passatempo).

3.2 Primeiros passos

Talvez a melhor forma de se passar a conhecer uma ferramenta previamente desconhecidaseja instalando-a, e em seguida rodando um simples exemplo para testá-la e familiarizar-se como 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ósrecomendamos. Não obstante, usuários de Windows podem seguir com o curso, assim comoos 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 de-rivados (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 depen-dentes, aceite.

Caso esteja usando outra distribuição, procure um pacote com este nome ou pygtk.

17

Page 19: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

3.3 Conferindo a instalação

OK, tecnicamente estamos prontos para seguir em frente e aprendermos os conceitos. Masprimeiro 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 ocurso 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á-lafunciona. Veremos os motivos mais adiante.

18

Page 20: Python gtk

Capítulo 4

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

4.1 Conceitos básicos

Antes de prosseguirmos com os exemplos, iremos dar uma breve olhada nos conceitos queserã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), otermo 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 parafer-nália que possa estar contida em uma janela. Em suma, tudo representado é um widget.

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çãocorrespondente. Este conceito é denominado sinal (entretanto este conceito é meramente seme-lhante aos signals Unix, a implementação é bastante diferente). Quando ocorre um evento, comoo apertar de um botão, o widget irá emitir um sinal. Os sinais variam de widget para widget. Porexemplo, 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;

19

Page 21: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

• 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 cursoiremos ver apenas os signals mais freqüentemente utilizados.

Callback

Quando um sinal ocorre, uma função callback pode ser acionada. Esta função pode alterara 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 umsignal? 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 argu-mento (name) indica o nome do sinal que irá acionar o callback (por exemplo "clicked"ou "des-troy"). O segundo argumento (func) indica a função (callback) que deverá ser acionada. Repareque o argumento é o *objeto* da função, e não o seu nome. No terceiro argumento, estão osdados 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âme-tro 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ásdo GTK+.

Eventos

Além dos sinais, existem também eventos, que refletem o mecanismo de eventos do X. Sãomuito similares a sinais, no sentido que callbacks também podem ser associados a estes. Re-fletem eventos tais como o requisitado fechamento de um programa, ou o clique do mouse (ouduplo-, 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)

20

Page 22: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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 mecanismode gerenciamento de eventos do GTK+. Se retornar True, significa que o evento já foi tratado enão deverá propagar (isto é, se houver mais de um callback associado a um evento). Se retornarFalse, então o evento será propagado.

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

Desconectando callbacks

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

object.disconnect (handler_id)

4.2 Um exemplo prático

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 pygtkimport 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 classeWindow. """

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

""" Ajustamos alguns parâmetros referentes à janela:- Ajusta o espaçamento da borda para 10 (espaço entreborda e os widgets)

- Seta o título da janela

21

Page 23: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

- 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 eventodelete_event. Caso isso não fosse feito, o programacontinuaria sua execução mesmo após o fechamento dajanela """

self.janela.connect ("delete_event", self.delete_event)

""" Em seguida cria-se um botão (perceba que é a isntância deuma classe. """

self.botao = gtk.Button ("Hey there")

""" IMPORTANTÍSSIMO: (quase) todo elemento deve serexplicitamente exibido para que apareça na tela. """

self.botao.show ()

""" Adiciona o botão à janela. Para adicionar mais elementosserá 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á dois elementos importantes neste exemplo: o callback e as chamadas a show().

22

Page 24: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

O método show() causa uma widget a ser exibida assim que possível. Antes de se chamareste método a widget não será mostrada! Naturalmente, para que uma widget seja visualizada, énecessário também que todos os contêineres da widget também sejam explicitamente mostrados.Quando um contêiner "toplevel"(que contém outros widgets) é mostrado, este é imediatamentemapeado e exibido na tela, assim como todos os widgets contidos dentro deste que já estejamexibidos. É 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 componentesdependendo da complexidade gráfica do GUI.

Outro aspecto importante do exemplo é o callback usado para o fechamento do programa.O evento "delete_event"é chamado quando o sistema operacional recebe uma solicitação de fe-chamento do programa. Isto pode ocorrer quando o usuário clica no X para fechar, ou pelogerenciador de tarefas. Em todo caso, se não tratarmos este evento a widget em questão (nocaso 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 quartoparâ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 neces-sariamente teve tal intenção. O browser Firefox confirma o fechamento da janela se mais de umaaba estiver aberta. O OpenOffice pergunta se deseja salvar o documento antes de fechar. É esteevento o responsável por essas ações.

23

Page 25: Python gtk

Capítulo 5

Lição 3 - Widgets elementares

5.1 Empacotando widgets

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

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

BoxesBoxes 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 noHBox eles podem ser inseridos da esquerda para a direita ou da direita para a esquerda, depen-dendo da forma como sejam criados. É comum usar uma combinação de boxes (boxes dentro deboxes) para criar o efeito desejado.

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

Vale frisar que botões são contêineres por si só, mas normalmente usa-se apenas um labeldentro 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 tenham exatamente amesma 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)

24

Page 26: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Box é o container onde o widget será empacotado e o parâmetro child deve ser o objeto do widgeta ser empacotado. Os outros parâmetros controlam como os widgets inseridos se adaptarão aobox (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 mantertodos 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 es-paç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 (fornecidono HBox() ou VBox())? O spacing é o espaço adicionado entre os elementos, e o padding é oespaç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 pygtkimport gtk

class Janela: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 Noneself.botao1.connect ("clicked", self.button_click, None)

25

Page 27: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

self.botao2.connect ("clicked", self.delete_event, None)

# Exibe-osself.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 HBoxself.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 contêiner, como veremos adianteself.janela.add (self.hbox)

# Exibe o hboxself.hbox.show ()

# Exibe a janelaself.janela.show ()

def delete_event (self, widget, event):gtk.main_quit()

def button_click (self, widget, event):print "Hullo"

def main (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 extre-mamente flexível.

26

Page 28: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

5.2 O widget do botão

Vimos no exemplo anterior que botões podem ser customizados com parâmetros adicionais.Já sabemos praticamente tudo sobre botões, mas há alguns truques dos quais devemos estarcientes.

A sintaxe básica para criar um botão é:

button = gtk.Button(label=None, stock=None)

O primeiro parâmetro especifica o texto a ser exibido (opcional) e o stock pode ser uma de váriasconstantes pré-definidas com padrões de botões (também opcional). O stock (STOCK_QUIT)usado no exemplo da lição anterior é um botão tipicamente usado para sair de programas. Avariedade completa está disponível em http://www.pygtk.org/docs/pygtk/gtk-stock-items.html.

Dica: Sendo a usabilidade um aspecto muito importante nos aplicativos de atualmente, é co-mum que programas suportem atalhos de teclado em vez de necessitar que se use o mouse. Poristo, para sublinhar uma letra do label, basta prefixá-la com ’_’. Isto se aplica a todos os botõesvistos nesta página. Assim, ao apertar Alt+(letra sublinhada), seria como se o usuário clicasse nobotão.

Customizando o visual

Há de se convir que as possibilidades são bastantes limitadas se não se pode ao menos criarum botão com um ícone customizado; tem de haver uma forma de se criar um botão diferenciado;e de fato existe. Analise o seguinte exemplo, botao3.py:

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

import pygtkimport gtk

class Janela: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 3")self.janela.resize (100, 50)

# 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())

27

Page 29: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

# Em seguida cria-se o botão (perceba a ausência do label)self.botao = gtk.Button ()

# Cria-se o box do botão...self.box = self.xpm_label_box ("tartan.xpm", u"faça algo!")

# E adiciona o HBox com os conteúdos do botãoself.botao.add (self.box)

# Exibe-osself.box.show()self.botao.show ()

# Adiciona o botão á janela. Para adicionar mais elementos# será necessário criar um container, como veremos adianteself.janela.add (self.botao)

# Exibe o hboxself.box.show ()

# Exibe a janelaself.janela.show ()

def xpm_label_box (self, xpm_arquivo, label_texto):# Cria-se o HBox não-homogêneo (o ícone é menor que o label)# e sem espaçamento.box = gtk.HBox (False, 0)

# Adiciona uma pequena borda como em um botãobox.set_border_width (2)

# NOVIDADE: cria a imagemimagem = gtk.Image()imagem.set_from_file (xpm_arquivo)

# Cria o labellabel = gtk.Label (label_texto)

# Adiciona a imagem e o label ao boxbox.pack_start (imagem, False, False, 3)box.pack_start (label, False, False, 3)

# Mostra tudoimagem.show()label.show()return box

28

Page 30: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

def main (self):gtk.main()

if __name__ == "__main__":janela = Janela()janela.main()

Preste atenção ao exemplo e perceberá que não é possível criar um botão com um pixmapdiferenciado "nativamente", na realidade criamos um HBox no qual estão contidos o pixmap eo label. O método que usamos, xpm_label_box, poderia com facilidade ser usado em qualqueroutro elemento que possa ser um contêiner.

A propósito, para se criar o pixmap podemos usar uma diversidade de programas, inclusive oopen-source GIMP.

Outros botões

Outras formas de botões são freqüentemente vistas, como toggle buttons (que possuem umrelevo para indicar se estão selecionados ou não), checkboxes (uma pequena caixa que podeser marcada ou desmarcada) e radio buttons (conjunto de botões dos quais apenas um pode serselecionado através de pequenas bolas). Na ausência de uma tradução melhor irei me referir aosnomes originais, em inglês.

Toggle buttons

Toggle buttons são derivados de botões normais e são muito similares, exceto o fato de quesempre estarão em um de dois estados (pressionado ou não), alterados através de um clique.Seu estado se altera a cada clique. Estes botões são a base para check buttons e radio buttons,com muitas similaridades na implementação.

Como criar um?

botao = gtk.ToggleButton(label=None)

Cada widget deste tipo possui uma função get_active() que retorna se o botão está pressionadoou não; o sinal que indica que o estado de um botão foi alterado é o "toggled"; juntando asduas peças do quebra-cabeça, rapidamente descobrimos como trabalhar com as mudanças deestados:

def toggle_button_callback (widget, data):if (widget.get_active()):# botão está pressionadoelse:# botão não está pressionado

29

Page 31: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

A função get_active() pode ser usada sempre que se precisar obter o estado do botão, sendoque esta retornará True (pressionado) ou False (não-pressionado).

E como alterar o estado do botão manualmente? Usa-se o seguinte método:

botao.set_active(active)

Onde active pode ser True (pressionado) ou False (não-pressionado). O valor inicial (quando obotão é gerado) é False.

Perceba que quando esta função for chamada, os sinais "clicked"e "toggled"serão emitidospelo botão!

Check buttons

Como já foi mencionado, seu funcionamento é muito parecido com toggle buttons, e de fato,são simplesmente toggle buttons com uma aparência diferente, já que os labels ficam na lateralda "caixinha"que o usuário marca. A criação é feita da seguinte forma:

botao = gtk.CheckButton(label=None)

O callback de verificação de estado (get_active()) pode ser feito da mesma forma que nos togglebuttons, assim como o ajuste de estado (set_active()).

Radio buttons

Radio buttons são similares aos check buttons, mas possuem a diferenciação de serem agru-pados de tal forma que apenas um pode estar selecionado por vez. Isto é bom quando a lista deopções é razoavelmente pequena.

A criação é feita com o seguinte comando:

botao = gtk.RadioButton (group=None, label=None)

Perceba a existência de um argumento extra. Radio buttons requerem de um grupo para funcio-nar. A primeira chamada para gtk.RadioButton() deverá passar como argumento de group None,e um novo grupo de radio buttons será criado com o novo botão.

Para adicionar mais radio buttons para o grupo, passe a referência para um radio button naschamadas subseqüentes a gtk.RadioButton().

É também uma boa idéia explicitar qual botão deverá estar apertado inicialmente com o co-mando

button.set_active(is_active)

Isto funciona da mesma forma como foi descrito acima. Uma vez que radio buttons estão agrupa-dos, apenas um do grupo pode estar ativo. Por este motivo, se o usuário clicar em um, depois em

30

Page 32: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

outro botão de dado grupo, o primeiro radio button irá emitir o sinal "toggled"(já que foi desativado)e o segundo botão também irá emitir o sinal "toggled"(já que acabara de ser pressionado).

Recapitulando

No intuito de fixar e exemplificar o que foi visto acima, preste atenção no exemplo botao4.py.

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

import pygtkimport gtk

class Janela:# Função callback que monitora o estado dos botõesdef callback (self, widget, data=None):print "Botao %s foi %s." % (data, ("desselecionado",s "selecionado")[widget.get_active()])

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 + botões")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())

vbox = gtk.VBox (True, 2)

toggle1 = gtk.ToggleButton("Toggle button 1")toggle1.connect ("toggled", self.callback, "Toggle button 1")toggle2 = gtk.ToggleButton("Toggle button 2")toggle2.connect ("toggled", self.callback, "Toggle button 2")

vbox.pack_start (toggle1, False, False, 2)toggle1.show()vbox.pack_start (toggle2, False, False, 2)toggle2.show()

checkbox1 = gtk.CheckButton("Checkbox 1")checkbox1.connect ("toggled", self.callback, "Checkbox 1")checkbox2 = gtk.CheckButton("Checkbox 2")checkbox2.connect ("toggled", self.callback, "Checkbox 2")

31

Page 33: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

vbox.pack_start (checkbox1, False, False, 2)checkbox1.show()vbox.pack_start (checkbox2, False, False, 2)checkbox2.show()

radio1 = gtk.RadioButton(None, "Radio button 1")radio1.connect ("toggled", self.callback, "Radio button 1")radio2 = gtk.RadioButton(radio1, "Radio button 2")radio2.connect ("toggled", self.callback, "Radio button 2")radio3 = gtk.RadioButton(radio2, "Radio button 3")radio3.connect ("toggled", self.callback, "Radio button 3")

vbox.pack_start (radio1, False, False, 2)radio1.show()vbox.pack_start (radio2, False, False, 2)radio2.show()vbox.pack_start (radio3, False, False, 2)radio3.show()

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

# Exibe-osvbox.show()

# Exibe a janelaself.janela.show ()

def main (self):gtk.main()

if __name__ == "__main__":janela = Janela()janela.main()

Screenshot do programa em ação:

32

Page 34: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Mensagens são emitidas no terminal a cada alteração nos botões.

Repare como a criação do radio button é diferente dos demais, assim como o seu funciona-mento.

33

Page 35: Python gtk

Capítulo 6

Lição 4 - Widgets miscelâneas 1

6.1 Adjustments

Um elemento muito frequente em interfaces com usuários é o "slider", uma barra de rolagematravé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 ateoria por trás de seu funcionamento.

Adjustments

Uma aplicação necessita reagir às ações de usuários nestes widgets; isto poderia ser feitoatravés de um sinal emitido pela widget quando houvesse uma mudança no seu valor, no quala widget transmite também o novo valor para a função responsável. Mas e se quiséssemos as-sociar os ajustes de várias widgets, de tal forma, que mudar o valor em uma widget alterariaoutra? Uma aplicação prática para isto seria conectar as barras de rolagem de tal forma a sele-cionar o conteúdo a ser visualizado, por exemplo, de uma imagem(Será isso um presságio?). Secada widget de ajuste tivesse de emitir um sinal a cada mudança de valor, o programador teriade 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 formaatravés da qual widgets podem transmitir informações sobre ajustes de uma forma abstrata eflexí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 parapropagar informações entre várias widgets separadas.

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

Criando um Adjustment

A sintaxe é simples:

34

Page 36: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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 emaior valores que podem ser assumidos pelo widget. Step_incr define o intervalo entre os ajus-tes, page_incr define o maior intervalo entre estes. Finalmente o page_size é o parâmetro queconté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 espe-cífica (por exemplo pixels) e aqueles que usam números arbitrários. Alguns widgets que usamnúmeros arbitrários incluem a barra de rolagem e a barra de progresso. Estas podem ser ajus-tadas 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 de rolagem. Estes necessitam va-lores em pixels para seus Adjustments. Alguns widgets que podem ser ajustados indiretamenteusando barras de rolagem, a exemplo do ScrolledWindow que veremos adiante.

Adjustments podem também ser manipulados manualmente. Para alterar o valor de um objetoAdjustment, usamos

adjustment.set_value(value)

Como já dissemos, Adjustments são capazes de emitir sinais (por serem derivados da classeObject, assim como outros widgets) e por este motivo mudanças se propagam automaticamentequando por exemplo uma barra de rolagem conectada a outra widget é alterada; todas widgetsajustáveis se conectam através do sinal value_changed.

6.2 Widgets de faixa de valores

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 objetoAdjustment, 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 apropria-das 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 wid-gets de escala, que são mais amigáveis e possuem mais funcionalidades.

Podemos criá-las através do seguinte comando (horizontal ou vertical):

hscroll = gtk.HSrollbar (adjustment=None)vscroll = gtk.VSrollbar (adjustment=None)

35

Page 37: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

O parâmetro pode ser um adjustment criado pela função mostrada na seção anterior. Naomissão deste será criado um adjustment automaticamente, que pode subseqüentemente serobtido 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 manipuleum valor em uma faixa específica. Pode ser usado, por exemplo, para alterar o zoom de umapágina ou o contraste de uma imagem.

Estes widgets possuem 2 tipos: 1 para widgets horizontais outro para widgets verticais (aversã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 emcomum. Caso seja omitido, o adjustment será criado pela função com todos os valores ajustadosem 0.0, o que não é muito útil. Como o page_size pode afetar o valor máximo da widget (além doespecificado pelo parâmetro upper), é recomendado que se ajuste o page_size em 0.0 para queo valor upper coincida com o maior valor que o usuário possa selecionar.

Opções

Algumas widgets de escala exibem o valor escolhido ao seu lado; isto pode ser feito atravésda 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 ajustadoatravé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 ouPOS_BOTTOM.

Política de atualização

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

36

Page 38: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

• UPDATE_CONTINUOUS: Emite o sinal value_changed continuamente, mesmo que a barraseja movida muito pouco;

• UPDATE_DISCONTINUOUS: Emite o sinal value_changed apenas quando o valor da wid-get 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, ouse 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 umawidget 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 pelawidget, mesmo que seus valores tenham sido alterados. Para tal seria adequado emitir o sinal"changed"através de adjustment.emit("changed").)

6.3 Labels

Labels (rótulos) estão entre os widgets mais simples, no entanto são um dos mais frequente-mente usados. Simplesmente exibem texto que não é editável pelo usuário, como o usado emum 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 posterior-mente à 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:

37

Page 39: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

label.set_line_wrap (wrap)

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

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

6.4 Áreas com barras de rolagem

Ainda no tópico de adjustments e widgets com faixa de valores, um dos widgets mais úteisque utilizam esse recurso é o ScrolledWindow. Consiste em uma área (um viewport) sendo queapenas uma parte pode ser exibida. Barras de rolagem nas laterais permitem que o usuárioselecione 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 istoser 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 wid-get. 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 abarra 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)

6.5 Exemplo

Temos a seguir um simples exemplo (misc1.py) que usa 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

38

Page 40: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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)

39

Page 41: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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()

# Contêiner 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)

40

Page 42: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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:

41

Page 43: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

42

Page 44: Python gtk

Capítulo 7

Lição 5 - Widgets miscelâneas 2

7.1 Barras de progresso

Iremos nesta lição continuar a exploração pelas widgets do GTK+. Todas estas são vistascom bastante freqüência.

Barras de progresso

Todo usuário as conhece; são usadas para representar o processo de uma operação. Comotudo 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 aliçã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á estarpreenchida.

É também possível que o preenchimento ocorra da direita para esquerda (ou outros), em vezde 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;

43

Page 45: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

• 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á ocor-rendo sem precisar 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: p

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

7.2 Dialogs

O widget Dialog é também conhecido como pop-up por alguns. Consiste em uma janela comalguns elementos empacotados (um vbox (chamado vbox) para conteúdo e um hbox (chamadoaction_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áriasopções de criação, dentre elas:

• DIALOG_MODAL - Faz com que o usuário não possa manipular a janela principal, apenasa que foi criada;

• DIALOG_DESTROY_WITH_PARENT - Força que o Dialog seja destruído quando sua janelaprincipal 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() novbox 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ãonormalmente, por exemplo).

44

Page 46: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

7.3 Barras de status

São widgets relativamente simples que exibem uma mensagem por vez. Servem para auxi-liar 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 oprogresso de um processo.

Para que permita que várias partes da aplicação utilizem a mesma barra de status, tem-se oque se chama de identificadores de contexto, que identificam os diferentes "usuários". Ela tam-bém tem uma pilha que assegura que a mensagem a ser exibida sempre será a que está no topoda 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émuma 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 depush). Como se pode perceber, cada parte do programa pode interagir com a barra de status deforma independente, já que terá seu próprio context_id.

7.4 Exemplo

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

45

Page 47: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Por motivos didáticos foi usado um timeout, tópico que não será visto neste curso, paraa atualização automatizada da barra de progresso. No entanto basta saber que timer = gob-ject.timeout_add(interval, function, ...) irá executar a cada intervalo milisegundos a função func-tion. 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

46

Page 48: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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)

47

Page 49: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

# 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)

48

Page 50: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

# 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())

# Contêiner 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

49

Page 51: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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:

50

Page 52: Python gtk

Capítulo 8

Lição 6 - Widgets miscelâneas 3

8.1 Menus

Em GTK+ existem várias formas possíveis de se criar menus. Neste curso iremos ver a formamais manual, por motivos didáticos. Os outros métodos abstraem parte do funcionamento o queacaba 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 usadotanto para criar os itens de menu que efetivamente realizam a ação solicitada pelo usuário (porexemplo "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()

51

Page 53: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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

menu = gtk.Menu()

Esta função retorna uma referência para um novo menu. Não é necessário chamar a funçãoshow(), 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 carac-teres mnemônicos precedidos de "_". É necessário que se chame a função show() pra que sejaexibido. Não confunda item de menu com menu! O primeiro é o botão associado a uma ação, eo 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 antesde adicioná-lo à barra de menus:

menu_item.set_right_justified (right_justified)

52

Page 54: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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 elementosde construção do menu, caso deseje automatizar este procedimento, é possívei tanto escreverfunções auxiliares ou usar as formas embutidas no GTK+: ItemFactory ou UIManager. DesdePyGTK 2.4, o uso do ItemFactory está depreciado, portanto deve-se usar o UIManager, queconstrói o menu a partir de uma estrutura XML.

8.2 Entrada de texto

Um elemento crucial de interfaces deixado de fora até o momento é o campo onde o usuáriopode entrar com conteúdo livre (texto). Em GTK+ um tal widget é o Entry. Este permite criar umcampo 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. Suaalteraçã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 taiscomo 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 desabilitar a edição de seu conteúdopor parte do usuário (onde editable pode ser True ou False), e permitir ou não a visualização doconteúdo sendo digitado. Isto pode ser útil em campos de senhas.

53

Page 55: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

8.3 Spin buttons

Este tipo de botão pode ser usado pelo usuário para se escolher entre uma faixa de valoresnuméricos. Seu funcionamento rege em torno dos Adjustments; reveja a lição caso seja neces-sá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 devalores do widget. O climb rate indica a quantidade de aceleração que o botão tem ao ser pres-sionado (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 incrementou page_increment (do Adjustment) caso increment seja igual a 0;

54

Page 56: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

• SPIN_STEP_BACKWARD - Diminui o valor do spin button de acordo com o valor incrementou 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 maisdetalhada:

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 ousuá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 maispró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 valormesmo que este seja inválido (após uma alteração), e o segundo ignora erros enquanto estiverconvertendo para valor numérico.

8.4 Diálogo de seleção de arquivo

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

55

Page 57: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Com isso em mente, os desenvolvedores do GTK+ incluiram isso como uma widget fácil dese 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 essaswidgets "internas"normalmente. Elas seguem o seguinte padrão de nomes:

56

Page 58: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

filesel.dir_listfilesel.file_listfilesel.selection_entryfilesel.selection_textfilesel.main_vboxfilesel.ok_buttonfilesel.cancel_buttonfilesel.help_buttonfilesel.history_pulldownfilesel.history_menufilesel.fileop_dialogfilesel.fileop_entryfilesel.fileop_filefilesel.fileop_c_dirfilesel.fileop_del_filefilesel.fileop_ren_filefilesel.button_areafilesel.action_area

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

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

57

Page 59: Python gtk

Capítulo 9

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

9.1 Alignment

O widget de alinhamento (Alignment) permite que se adicione um widget em uma posição etamanho relativo ao widget de alinhamento. Por exemplo, pode ser usado para se centralizar umbotã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âmetrosespecificados. Os valores são em ponto-flutuante, e devem variar entre 0.0 e 1.0. O xalign eyalign ajustam a posição do widget no Alignment. Estas propriedades especificam a fração deespaç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 deveser absorvido pela widget: 0.0 não absorve nenhum espaço, e 1.0 absorve todo o espaço vaziodisponível. Naturalmente se ambos xscale e yscale forem iguais a 1.0, então o uso do widget dealinhamento 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:

58

Page 60: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

9.2 Contêiner Fixed

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 dinami-camente.

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). Osegundo adiciona a widget desejada (widget) ao widget fixo (fixed) na posição x e y. O terceiromeramente muda a widget de posição.

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

Veja o seguinte exemplo:

59

Page 61: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Estes devem ser usados com cautela, já que algumas configurações locais (como tamanhode fontes) serão ignorados, como a posição é absoluta.

9.3 Contêiner layout

O contêiner Layout é bastante similar ao último visto (Fixed), com a exceção de que ele im-plementa 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 barrasde 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 Layoutirá 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:

60

Page 62: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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 manu-almente.

Veja o seguinte exemplo:

9.4 Frames

Frames normalmente são usados para agrupar widgets de forma clara e objetiva. Ao contráriodos ú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 partesdistintas 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)

61

Page 63: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

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:

9.5 Paned Window

Muitas vezes, por exemplo em um programa de e-mail, se deseja dividir uma área em 2 partestal que o usuário possa controlar o tamanho de cada uma dessas áreas. O GTK+ permite que sefaç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 oadicionará ao painel inferior (ou direito).

62

Page 64: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

63

Page 65: Python gtk

Capítulo 10

Lição 8 - Progredindo com PyGTK

10.1 Progredindo com PyGTK

O que foi visto neste curso serve apenas de base para que o programador possa se aventurarnas aplicações mais avançadas do Python/GTK+. Com algumas centenas de funções, boa partedo conteúdo não foi visto porque o curso se tornaria repetitivo, mas a base para seu entendimentopleno está presente no curso.

Algumas fontes recomendadas para o contínuo aprendizado:

http://www.pygtk.org/http://www.pygtk.org/tutorial.htmlhttp://www.pygtk.org/reference.html

Com isto encerra-se a matéria do curso propriamente dito.

Vale frisar que o curso foi bastante teórico, e permite ao programador entender todos os con-ceitos e conhecer boa parte dos widgets e seu funcionamento. No entanto existem métodos maisfáceis de se realizar a tarefa de diagramação de interfaces usando-se ferramentas tais comoGlade. Por não ser matéria do curso em si, veremos isso apenas de forma superficial.

10.2 Matéria extra: Criando interfaces gráficas usando PyGTK eGlade

O primeiro passo é a instalação. No Debian e derivados, os pacotes necessários são python-glade2 (contém as bibliotecas para o Python) e glade-2 (contém o construtor de interfaces). Por-tanto como usuário root execute o seguinte comando:

apt-get install python-glade2 glade-2

Em seguida execute o glade-2, para se deparar com o seguinte:

64

Page 66: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Inicialmente o Glade abre com um projeto novo e vazio. Repare que o projeto não contémjanelas ainda. Clique no ícone da janela na paleta (o primeiro ícone) que isto automaticamentecria uma janela vazia. Em seguida, é possível alterar as propriedades do elemento recém-criado,no caso a janela. Em "Propriedades"altere Name para JanelaPrincipal e Title para o que quiser.

Para adicionar elementos na janela, eles são "empacotados". Tendo a noção de como funci-ona no nível do código fonte (ou seja, tendo feito o curso) o programador já tem todo o conheci-mento que precisa para criar interfaces com facilidade.

Vamos criar uma interface muito simples, com apenas 2 widgets: um label e um botão. Por-tanto siga os seguintes passos:

65

Page 67: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

1. Clique no botão VBox (Vertical Box) na palheta;

2. Em seguida clique na janela para criar o VBox. Irá parecer uma janela solicitando o númerode células; reduza o valor para 2;

3. Clique no botão Label na palheta;

4. Clique na primeira célula do VBox recém-criado para adicioná-lo lá.

Viu? Temos um VBox com um elemento empacotado. Podemos alterar o conteúdo desterótulo para algo mais apropriado. Como a janela Properties sempre exibe as propriedades dawidget selecionada, mude o campo Label para "Clique abaixo!"Da mesma forma é possível alterarmuitas outras características que foram vistas ao longo do curso. Lembre-se de experimentar osajustes disponíveis também nas outras abas, tais como Packing.

Falta agora somente o botão; clique no seu respectivo botão na palheta e clique na segundacélula do VBox para adicioná-lo. Em seguida altere o seu nome (Name) para botao1 e o rótulo(Label) para "Clique em mim."

Ao término deste processo devemos ter algo assim:

66

Page 68: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Clique em Project –> Save para salvar o projeto em uma pasta própria. O resultado dissoserão 2 arquivos XML que descrevem a interface. Abra-os em um editor de texto para ter umanoção de como a interface é descrita.

Ou seja, o Glade não gera código em si, e sim uma descrição. O python-glade2 foi instaladopor esse motivo: permitir com que o código faça uso de arquivos .glade.

OK, para ver a interface em funcionamento, crie um arquivo com o seguinte conteúdo:

import sysimport pygtk

67

Page 69: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

import gtkimport gtk.glade

class GladeTest:def __init__ (self):self.wTree = gtk.glade.XML("project2.glade")self.window = self.wTree.get_widget("window1")gtk.main()

if __name__ == "__main__":glade_test = GladeTest()

Execute-o e verifique seu funcionamento.

Perceba que a biblioteca gtk.glade está sendo usada; esta foi instalada no início da lição. Aprimeira chamada dentro do __init__ carrega a interface contida no arquivo XML (vide documen-tação aqui):

Este objeto respresenta uma ’instanciação’ da interface descrita em XML. Quando um dessesobjetos é criado, o arquivo XML é lido, e a interface é criada. O objeto gtk.glade.XML provê umainterface para acessar as widgets através dos nomes associados a estas na descrição XML.

A segunda carrega o widget especificado que, no caso, é uma janela. Finalmente gtk.main()inicia a execução.

Mas e se quiséssemos usar sinais e eventos assim como fizemos até o momento? Vamos lá...

O primeiro passo é conectar o evento "destroy"da janela à função gtk.main_quit() como fize-mos em todos os programas até o momento. Volte ao Glade e selecione a janela principal noprojeto. Vá para a janela de propriedades e escolha a aba Signals. Em "Signal"escolha "des-troy"(disponível em GtkObject).

68

Page 70: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

E clique em "Add"para adicioná-lo:

Com isso criamos um handler que funciona de forma semelhante a um sinal.

Faremos o mesmo para o botão; clique no botão "Clique em mim", e na janela Propriedades(aba Signals) escolha o sinal "clicked". Em seguida clique em add.

69

Page 71: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

Logo temos 2 handlers a gerenciar: on_window1_destroy e on_botao1_clicked. Esses nomespodem ser alterados, mas é recomendável que sigam um padrão.

Como, agora, fazer uso desses handlers? A biblioteca do glade para Python permite que issoseja de forma fácil, atribuindo vários handlers a funções diferentes. Veja o código abaixo:

import sysimport pygtkimport gtkimport gtk.glade

class GladeTest:def botao_clicked (self, widget):print "botao clicado"

def __init__ (self):self.wTree = gtk.glade.XML("project2.glade")self.window = self.wTree.get_widget("window1")dic = { "on_window1_destroy" : gtk.main_quit,"on_botao1_clicked" : self.botao_clicked }

self.wTree.signal_autoconnect (dic)gtk.main()

if __name__ == "__main__":

70

Page 72: Python gtk

CDTC Centro de Difusão de Tecnologia e Conhecimento Brasil/DF

glade_test = GladeTest()

Salve este código em um arquivo na mesma pasta do projeto Glade e execute-o. O resultadoé simples:

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.

10.3 Despedidas

Infelizmente o curso não irá se aprofundar mais do que isso em Glade, ficando isso a cargodo 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 alunoque nunca pare de aprender novas tecnologias e aprofundar-se nas existentes; busque cursos,sites, leia, mas não fique parado!

Espero que tenham gostado!

71