Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Python Tkinter desenvolvimento, Manuais, Projetos, Pesquisas de Informática

Tkinter em linguagem de programação python

Tipologia: Manuais, Projetos, Pesquisas

2019

Compartilhado em 23/10/2019

BrunoFreitas96
BrunoFreitas96 🇧🇷

4

(2)

2 documentos

1 / 49

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
As três Fates
Steven Ferg (steve@ferg.org)
Traduzido e adaptado por J. Labaki
labaki@feis.unesp.br
Grupo Python
Departamento de Engenharia Mecânica
UNESP – Ilha Solteira
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31

Pré-visualização parcial do texto

Baixe Python Tkinter desenvolvimento e outras Manuais, Projetos, Pesquisas em PDF para Informática, somente na Docsity!

As três Fates

Steven Ferg (steve@ferg.org)

Traduzido e adaptado por J. Labaki labaki@feis.unesp.br Grupo Python Departamento de Engenharia Mecânica UNESP – Ilha Solteira

P E N S A N D O E M T K I N T E R

TT095 – Métodos gerenciadores de janelas & controlando o tamanho de janelas com a opção geometry****.

  • Sobre Pensando em Tkinter Índice
  • Os programas
  • TT000 – Introdução
    • As quatro questões básicas da programação de GUIs
    • Alguns jargões da programação de GUIs
    • Sobre o Event Loop
  • TT010 – O programa em Tkinter mais simples possível: três linhas.
  • TT020 – Criando um objeto GUI e fazendo pack; containeres versus widgets.
    • Frames são elásticos
  • TT030 – Criando um Widget e colocando-o no frame.
  • TT035 – Usando a estrutura de classes no programa.
    • Por que estruturar sua aplicação como uma classe?
    • Quando introduzir a estrutura de classes
  • TT040 – Algumas formas diferentes de definir um widget.
  • TT050 – Empacotando.
    • Porque os botões apareceram verticalmente no último programa
    • Alguns termos técnicos – Orientação
  • TT060 – Fazendo Binding.
  • TT070 – Mexendo com foco e ligando eventos de teclado a widgets.
  • TT074 – Command Binding.
  • TT075 – Usando event binding e command binding juntos.
    • Para quais eventos serve command binding?
    • Usando event binding e command binding juntos
  • TT076 – Compartilhando informações entre alimentadores de eventos.
    • Compartilhando informações entre funções alimentadoras de eventos
    • Primeira solução – usar variáveis globais
    • Segunda solução – usar variáveis instanciadas
  • TT077 – Transmitindo argumentos para alimentadores de eventos I: O problema.
    • Características mais avançadas de command binding
  • TT078 – Transmitindo argumentos para alimentadores de eventos II: Usando Lambda.
  • TT079 – Transmitindo argumentos para alimentadores de eventos III: Usando Currying.
    • Sobre Curry
    • Curry – como usá-lo
    • Lambda versus Curry & event_lambda: qual devo usar?
  • TT080 – Opções de widget e configurações de pack
    • Três técnicas de controlar o layout de uma GUI
  • TT090 – Posicionando frames
  • TT100 – Opções de pack: side, expand, fill e anchor.
    • Um jeito prático de encontrar erros

P E N S A N D O E M T K I N T E R

TT000 – Introdução.

Eis alguns programas que começarão a explicar como pensar em Tkinter. Neles, como já disse, não atento para todos os tipos de widgets, atributos e métodos disponíveis em Tkinter, tampouco tento dar uma introdução detalhada sobre Tkinter, somente tento iniciar você no caminho para entender os seus conceitos básicos. No decorrer do programa de ensino, a discussão é dedicada exclusivamente ao gerenciador de geometria pack. Não falaremos sobre os gerenciadores grid ou place. As quatro questões básicas na programação de GUIs. Quando você desenvolve uma interface com o usuário (IU) há um conjunto padrão de questões que você deve satisfazer.

  1. Você deve especificar como você quer que a IU se pareça. Isto é, você precisa escrever um código que determina o que o usuário verá na tela do computador;
  2. Você deve decidir o que quer que a IU faça. Isto é, você deve escrever procedimentos que satisfaçam as necessidades do programa;
  3. Você precisa associar o parecer com o fazer. Isto é, você deve escrever um código que associa as coisas que o usuário vê na tela com os procedimentos que você escreveu para desempenhar os papéis requeridos pelo programa;
  4. Finalmente, você deve escrever um código que senta e espera pela entrada do usuário. Alguns jargões da programação de GUIs. A programação GUI (Graphic User Interface – Interface Gráfica com o Usuário) tem alguns jargões especiais associados às suas questões básicas.
  5. Nós especificamos como queremos que um GUI se pareça descrevendo os “ widgets ” que queremos exibir, e suas relações especiais (por exemplo, o quanto um widgets está abaixo ou acima, ou à direita ou à esquerda de outros widgets). A palavra “ widget ” é um termo sem tradução que designa “componentes de interface gráfica com o usuário” de um modo geral. Widgets inclui elementos como janelas, botões, menus e itens de menus, ícones, listas rolantes, barras de rolagem, etc.
  6. Os procedimentos que executam as tarefas dos GUIs são chamados “ event handler ”. “Events” são formas de entrada de dados como cliques de mouse ou digitação no teclado. Esses procedimentos são chamados “handlers” (alimentadores) porque eles “alimentam” (isto é, respondem a) estes eventos.
  7. A associação de um event handler a um widget é chamada “binding”. De modo geral o processo de binding envolve a associação entre três coisas diferentes: 4

P E N S A N D O E M T K I N T E R a. Um tipo de evento (por exemplo, um clique no botão esquerdo do mouse, ou pressionar a tecla ENTER), b. Um widget (por exemplo, um botão) e c. Um procedimento event handler. Por exemplo, nós precisamos fazer binding (a) num clique com o botão esquerdo do mouse no (b) botão “FECHAR” na tela para (c) executar o procedimento “fechePrograma”, que fechará a janela e desligará o programa.

  1. O código que senta e espera pela entrada de dados é chamada de “event loop”. Sobre o Event Loop Se você tem visto filmes, sabe que toda cidadezinha tem uma vovó que perde todo seu tempo debruçada na janela, só olhando. Ela vê tudo que acontece na vizinhança. Uma parte disso não tem graça, é claro – só pessoas subindo e descendo a rua. Mas a outra é interessante – como uma bela briga entre os pombinhos recém-casados do outro lado da rua. Quando algo interessante acontece, essa vovozinha cão-de-guarda imediatamente corre para o telefone contar tudo à polícia da vizinhança. O Event Loop é algo como essa vovozinha: gasta todo seu tempo esperando que eventos aconteçam. Muitos dos eventos não têm importância (como clicar num ponto neutro da janela), e quando os vê, não faz nada. Mas quando vê alguma coisa interessante – um evento que ele sabe, por meio de um binding de event handler , que é interessante (como um clique num dos botões da janela) – então imediatamente contata os event handler e faz com que saibam que o evento aconteceu. Comportamento do Programa Este programa facilita a você o entendimento da programação de interfaces com o usuário mostrando como estes conceitos básicos são implementados em um programa muito simples. Este programa não usa Tkinter ou qualquer forma de programação GUI, somente coloca um menu e um console, e recebe caracteres digitados no teclado como entrada. Assim, como você pode ver, ele satisfaz as quatro questões básicas da programação de interfaces com o usuário. #Questão 2: Define os procedimentos de event handler def handle_A(): print "Wrong! Try again!" def handle_B(): print "Absolutely right! Trillium is a kind of flower!" def handle_C(): print "Wrong! Try again!" #Questão 1: Define a aparência da tela print "\n"*100 # clear the screen print " VERY CHALLENGING GUESSING GAME" print "========================================================" 5

P E N S A N D O E M T K I N T E R pelo próximo evento, ou até que aconteça um evento que “destrua” a raiz. Um evento destruidor pode ser o fechamento da janela pelo botão X de fechamento. Quando a raiz é destruída, a janela é fechada e o event loop cancelado. Comportamento do programa Ao rodar este programa, você verá (graças ao Tk) a janela toplevel automaticamente com os widgets para minimizar, maximizar e fechar a janela. Tente usá-los – você verá que eles realmente funcionam. Clicando no widget “fechar” (o X em uma caixa, do lado direito da barra de título) será gerado um evento destruidor terminando o event loop principal, que no caso deste programa é mainloop. E desde que não haja mais nada depois da linha “root.mainloop()”, como neste caso, o programa não faz mais nada e se encerra. from Tkinter import * ###(1) root = Tk() ###(2) root.mainloop() ###(3)

TT020 – Criando um objeto GUI e fazendo pack; containeres versus

widgets.

Agora daremos uma pincelada em outra das quatro questões básicas da programação GUI – especificar como a GUI deverá parecer. Neste programa, introduzimos três dos maiores conceitos da programação em Tkinter:  criar um objeto GUI e associá-lo com seus mestres;  pack e  container versus widget. De agora em diante, distinguiremos os componentes entre containeres e um widgets. Como usarei sempre estes termos, um widget é um componente GUI que (geralmente) é visível e faz coisas. Já um container é simplesmente um container – uma cesta, como queira – dentro do qual dispõem-se os widgets. Tkinter oferece vários tipos de containeres. “Canvas” é um container para aplicações de desenho, e o container mais freqüentemente utilizado é o “Frame”. Frames são oferecidos pelo Tkinter como uma classe chamada “Frame”. Uma expressão como: Frame(meuMestre) 7

P E N S A N D O E M T K I N T E R cria uma instância da classe Frame (isto é, cria um frame), e associa a instância ao seu mestre, meuMestre. Outra maneira de ver isso é como uma expressão que adiciona um frame “escravo” ao componente meuMestre. Então, neste programa (linha 1), myContainer1 = Frame(myParent) cria um frame cujo mestre é myParent (isto é, a raiz), e dá a ele o nome de “myContainer1”. Resumindo, ele cria um container dentro do qual podemos agora colocar widgets. (Nós não colocaremos nenhum widget neste programa, somente posteriormente). Perceba que a relação mestre/escravo aqui é somente lógica, não tem nada de visual. Esta relação existe para otimizar eventos do tipo destrutivo – isso porque quando um componente mestre (como root) é destruído, o mestre sabe quem são seus escravos, e pode destruí-los antes de se destruir. (2) A próxima linha define o gerenciador de geometria “pack” para administrar myContainer1. myContainer1.pack() Simplesmente designado, “pack” é um método que transforma em visuais as relações entre os componentes GUI e seus mestres. Se você não definir o componente pack ou outro gerenciador de geometria, nunca verá a GUI. Um gerenciador de geometria é essencialmente um API – um meio de dizer ao Tkinter como você quer que containeres e widgets se apresentem visualmente. Tkinter oferece três gerenciadores para esta finalidade: pack, grid e place. Pack e grid são os mais usados por serem mais simples. Todos os exemplos em “Pensando em Tkinter” usam pack como gerenciador de geometria. O esquema padrão básico da programação em Tkinter, que veremos ainda diversas vezes, funciona mais ou menos assim:  uma instância (de um widget ou um container) é criada, e associada ao seu mestre;  a instância é administrada por um gerenciador de geometria. Comportamento do programa Quando você roda este programa, ele se parecerá muito com seu antecessor, exceto pelo tamanho. Isso é porque... 8

P E N S A N D O E M T K I N T E R atributos de button: a cor de fundo e o texto. Faremos isso mudando os valores do seu dicionário referentes às chaves “text” e “background”. button1["text"] = "Hello, World! " button1["background"] = "green" (4) E, é claro, nós fazemos pack no botão button. button1.pack() Comportamento do programa Quando você rodar este programa, deverá ver que o Container1 agora contém um botão verde com o texto “Hello, World!”. Quando você clica nele não acontece nada, porque nós ainda não especificamos o que queremos que aconteça quando o botão for clicado, se bem que o faremos mais tarde. Por ora, você deverá clicar no botão X da barra de título para fechá-lo, como antes. from Tkinter import * root = Tk() myContainer1 = Frame(root) myContainer1.pack() button1 = Button(myContainer1) ### (1) button1["text"]= "Hello, World!" ### (2) button1["background"] = "green" ### (3) button1.pack() ### (4) root.mainloop()

TT035 – Usando a estrutura de classes no programa.

Neste programa, introduziremos o conceito de aplicações de Tkinter estruturadas como classes. Nele, criamos uma classe chamada MyApp e transcrevemos alguns códigos dos programas anteriores para dentro de seu método construtor (init). Nesta versão reestruturada do programa, fazemos 3 coisas diferentes: (1) Em nosso código, designamos uma classe (MyApp) que define como queremos que a GUI se pareça e que tipo de coisa queremos fazer com isso. Todo este código é inserido no método construtor da classe. 10

P E N S A N D O E M T K I N T E R (2) Quando o programa é executado, a primeira coisa que ele faz é criar uma instância da classe. A linha que cria a instância é myapp=MyApp(root) Perceba que o nome da classe é “MyApp” (observe o jogo de maiúsculas) e o nome da instância é “myapp” (agora tudo minúsculo). Perceba também que essa linha faz de “root”, a raiz, um argumento dentro do método construtor de MyApp. O método construtor reconhece root sob o nome “myParent”. (3) Finalmente, deixamos a raiz em mainloop. Por que estruturar sua aplicação como uma classe? Uma das razões para usar uma estrutura de classes em seu programa é simplesmente controlá-lo melhor. Um programa estruturado em classes é provavelmente – especialmente se seu programa for muito grande – muito mais fácil de ser entendido. Uma consideração muito importante é que estruturar sua aplicação como uma classe ajudará você a evitar o uso de variáveis globais. Eventualmente, conforme seu programa for crescendo, você provavelmente irá querer que alguns de seus event handler consigam compartilhar informações entre si. Uma maneira é usar variáveis globais, mas é uma técnica muito maçante. Um caminho muito melhor é usar instâncias (isto é, usar “self.” nas variáveis), e para isso você precisa estruturar sua aplicação como classes. Exploraremos esse tópico em outros programas desta série. Quando introduzir a estrutura de classes Temos introduzido a noção de estrutura de classes para programas de Tkinter logo cedo para podermos explicá-la e partir para outros assuntos. Porém, no andar da carruagem, você poderá escolher proceder de outra forma. Em muitos casos, um programa em Tkinter começa com um script simples. Todo o código acontece numa única linha, como nossos programas anteriores. Então, conforme a aplicação toma corpo, o programa cresce, de forma que em pouco tempo você se verá envolvo por uma porrada de código. Você pode começar a usar variáveis globais... talvez uma porrada de variáveis globais. O programa começa a ficar difícil de entender e editar. Quando isso acontece, é hora de voltar à prancheta e refazer tudo, desta vez usando classes. Por outro lado, se você se sentir bem com classes, e tem uma boa idéia da forma final do seu programa, comece estruturando-o em classes desde o começo. Por outro lado (voltamos assim ao lado anterior?), logo no começo do processo de desenvolvimento (como observou Gerrit Muller) freqüentemente você ainda não sabe a 11

P E N S A N D O E M T K I N T E R (3) Para o botão button3, vemos que o método configure pode ter muitos argumentos, então designamos várias opções em uma única linha. (4) Nos exemplos anteriores, fazer um botão era uma tarefa em dois passos: primeiro criar o botão e então configurar suas propriedades. Também é possível configurar estas propriedades ao mesmo tempo em que criamos o botão. O widget “Button”, como qualquer widget, espera como primeiro argumento o nome do seu mestre. Depois desse argumento você pode, se desejar, adicionar um ou mais argumentos sobre as propriedades do widget. Comportamento do programa Quando você rodar este programa, deverá ver que o Container1 agora contém, junto com o antigo botão verde, mais três botões. Veja como myContainer1 (o frame) se estica para acomodar todos estes botões. Perceba também que esses botões são empilhados um sobre o outro. No próximo programa, veremos por que eles se arranjam dessa forma, e veremos como arranjá-los de forma diferente. from Tkinter import * class MyApp: def init(self, parent): self.myContainer1 = Frame(parent) self.myContainer1.pack() self.button1 = Button(self.myContainer1) self.button1["text"] = "Hello, World!" ###(1) self.button1["background"] = "green" ###(1) self.button1.pack() self.button2 = Button(self.myContainer1) self.button2.configure(text="Off to join the circus!") ###(2) self.button2.configure(background="tan") ###(2) self.button2.pack() self.button3 = Button(self.myContainer1) self.button3.configure(text="Join me?",background="cyan")#(3) self.button3.pack() self.button4 = Button(self.myContainer1, text="Goodbye!", background="red" ) ###(4) self.button4.pack() root = Tk() myapp = MyApp(root) root.mainloop() 13

P E N S A N D O E M T K I N T E R

TT050 – Packing.

No último programa, nós vimos quatro botões, empilhados um sobre o outro. Entretanto, provavelmente gostaríamos de vê-los lado a lado em alguma ocasião. Neste programa fazemos isso, e começaremos a ver as possibilidades que pack() oferece. (1) (2) (3) (4) Fazer pack é um das maneiras de controlar a relação visual entre os componentes da GUI. O que faremos agora é usar a opção “side” como argumento de pack para colocar os botões lado a lado, desse jeito: self.button1.pack(side=LEFT) Veja que LEFT (assim como RIGHT, TOP e BOTTOM) são constantes de nomes bem amigáveis definidas em Tkinter. Isto é, “LEFT” deveria aparecer no código como “Tkinter.LEFT”, mas por causa da nossa maneira de importar o módulo Tkinter (página 6), não precisamos mais usar o prefixo “Tkinter.”. Porque os botões apareceram verticalmente no último programa Como você se lembra, no último programa nós simplesmente empacotamos os botões sem especificar a opção “side”, e os botões ficaram daquela forma, empilhados. Isso aconteceu porque a opção pré-designada da opção “side” é TOP. Então, quando fizemos pack no botão button1, ele foi colocado no topo da cavidade do frame myContainer1. Ao fazer pack sem argumentos sobre o botão button2, ele também é colocado no topo da cavidade deste frame, que neste caso fica exatamente abaixo do botão button1, e assim por diante. Se nós tivéssemos feito pack nos botões em ordem diferente – por exemplo, se tivéssemos feito pack em button2 primeiro, e depois em button1 – suas posições teriam sido invertidas: o botão button2 estaria em cima. Então, como você pode ver, uma das maneiras de controlar como sua GUI vai se parecer é controlando a ordem de fazer pack em cada um dos widgets dentro do container. Alguns termos técnicos – “Orientação” Orientação vertical inclui os lados TOP (de cima) e BOTTOM (de baixo). Orientação horizontal inclui os lados LEFT (esquerdo) e RIGHT (direito). Quando você está empacotando widgets e containeres, é possível mesclar dois tipos de orientação. Por exemplo, podemos precisar posicionar um botão com orientação vertical (como TOP) e outro com orientação horizontal (como LEFT), mas fazer isso misturando orientações dentro do container não é uma boa idéia. Se você misturar orientações poderá prejudicar a maneira como os objetos aparecerão na tela, além da bela surpresa que terá se precisar redimensionar a janela depois. 14

P E N S A N D O E M T K I N T E R Você deve se lembrar da discussão de nosso primeiro programa, de que uma das questões básicas da programação GUI é o “binding”. Binding é o processo de definir a conexão ou relação (geralmente) entre:  um widget;  um tipo de evento e  um alimentador de eventos. Um alimentador de eventos é um método ou sub-rotina que alimenta eventos quando eles ocorrem. Talvez ajude dizer que em Java, alimentadores de eventos são chamados “listeners” (vigilantes), um nome bem sugestivo considerando sua função – estar atento aos eventos e responder a eles. Em Tkinter, uma maneira de criar bindings é pelo método bind(), da seguinte forma: widget.bind( nome_do_tipo_de_evento , nome_do_alimentador_de_eventos ) Esse tipo de ligação é chamado “event binding”. Há outro jeito de ligar um alimentador de eventos a um widget, chamado “command binding” e nós a veremos em alguns programas daqui pra frente. Por ora, vejamos melhor o event binding, e tendo entendido este, será moleza explicar o command binding. Antes de começarmos, vamos esclarecer uma coisa: a palavra “botão” pode ser usada para designar duas coisas inteiramente diferentes:  um widget, Button – uma GUI que é mostrada no monitor do computador e  um botão no seu mouse – aquele que você pressiona com o dedo. Para evitar confusão, procuraremos distingui-los como “o botão” e “o botão do mouse”, em vez de simplesmente “botão”. (1) Nós ligamos o evento <Button-1> (um clique com o botão esquerdo do mouse) sobre o botão button1 ao método self.button1Click. Quando button1 é clicado com o botão esquerdo do mouse, o método self.button1Click() é chamado para alimentar o evento. (3) Veja que, embora não tenhamos especificado na operação de binding, self.button1Click () receberá dois argumentos. O primeiro, é claro, será “self”, primeiro argumento para qualquer método de classes em Python. O segundo será um objeto evento. Esta técnica de binding e evento – isto é, usando o método bind() – sempre implica na utilização de um objeto evento como argumento. Em Python/Tkinter, quando um evento ocorre, toma forma de um objeto evento. Um objeto evento é extremamente útil porque carrega consigo uma coleção de informações úteis e 16

P E N S A N D O E M T K I N T E R métodos. Você pode examinar o objeto evento para encontrar que tipo de evento ocorreu, o widget onde ocorreu, e outras informações úteis. (4) Então, o que acontece quando button1 é clicado? Bem, neste caso nós o designamos para fazer algo bem simples: mudar sua cor de verde para amarelo e vice-versa. (2) Vamos fazer o button2 (o botão do “Tchau!”) fazer algo mais útil: fechar a janela. Para isso ligamos o evento de clicar com botão esquerdo do mouse sobre o button2 ao método button2Click() e (6) Fazemos o método button2Click() destruir a janela raiz, a mestra de myapp. Isso vai ter um efeito bem devastador, porque todos os escravos também serão destruídos. Na verdade, toda a GUI será destruída. É claro que para isso, myapp tem que saber quem é sua mestra (aqui, a janela raiz). Então adicionamos um código (7) ao construtor da classe para lembrá-la disso. Comportamento do programa Quando você roda este programa, vê dois botões. Clicar no botão “OK” o faz mudar de cor. Clicar no botão “Cancel” fecha a aplicação. Quando a GUI é aberta, se você apertar TAB, verá que o foco do teclado vai ficar pulando entre os dois botões, embora apertar ENTER no teclado não faça nada. Isso é porque temos ligado somente cliques de mouse aos nossos botões, não eventos de teclado. Os próximos tópicos falarão deste assunto. Finalmente, observamos que os botões têm tamanhos diferentes porque os textos que contêm têm tamanhos diferentes. Só por causa disso. Não fica muito elegante assim, por isso consertaremos esse “problema” no próximo programa. from Tkinter import * class MyApp: def init(self, parent): self.myParent = parent ### (7) lembra seu mestre, a raiz self.myContainer1 = Frame(parent) self.myContainer1.pack() self.button1 = Button(self.myContainer1) self.button1.configure(text="OK", background= "green") self.button1.pack(side=LEFT) self.button1.bind("<Button-1>", self.button1Click) ### (1) self.button2 = Button(self.myContainer1) self.button2.configure(text="Cancel", background="red") 17

P E N S A N D O E M T K I N T E R passar de uma Fate a outra, assim elas podiam se revezar entre ver ou não. É claro, se você conseguisse roubar esse olho, teria algo valiosíssimo para barganhar o que quisesse com elas. “Foco” é o que permite aos widgets da sua GUI ver os eventos de teclado. O foco está para os widgets da sua GUI como o olho estava para as Fates. Somente um widget por vez pode ter o foco, e o widget que o tem é o que vê, e responde a, os eventos de teclado. Neste programa, por exemplo, nossa GUI tem dois botões, “OK” e “Cancel”. Supondo que eu pressione o botão ENTER no teclado, será que ele será visto pelo botão “OK” indicando que o usuário está confirmando sua escolha? Ou será que o ato de pressionar esta tecla será visto pelo botão “Cancel”, indicando que o usuário está cancelando (e destruindo) a aplicação? Tudo isso depende de onde está o foco. Isto é, depende de que botão “tem foco”. Como as Fates, que passavam seu olho de uma a outra, o foco pode ser passado de um widget na GUI para outro. Há várias formas de fazer isso. Uma delas é clicando no widget com o botão esquerdo do mouse (esse modo funciona em Windows e Macintosh, em Tk e Tkinter. Há alguns sistemas que usam a convenção “foco segue o mouse”, em que o widget que está sob o mouse tem foco automaticamente – não é necessário clicar) Outra maneira de mudar o foto é usando o fato de que os widgets são adicionados a uma lista conforme são criados. Pressionando a tecla TAB, o foco se move do widget atual para o próximo da lista. O widget seguinte ao último é o primeiro. Pressionando SHIFT+TAB, o foco se move para o item anterior da lista. Quando um botão GUI tem foco, isso é indicado por uma caixinha de pontos em torno do texto do botão. Para ver isso, rode o programa anterior. Quando o programa começa, nenhum dos botões tem foco, por isso nenhum deles tem a caixa de pontos. Pressione TAB e você verá essa caixa em torno do texto do botão esquerdo, mostrando que o foco está sobre ele. Agora pressione várias vezes TAB e observe o foco pular de um botão a outro repetidamente. (0) Neste programa, queremos que o botão OK tenha foco desde o começo. Para isso usamos o método focus_force(), que força o foco a começar no botão OK. Quando você roda o programa, verá a caixa de pontos sobre o botão OK desde que a aplicação se abrir. No último programa, nossos botões respondiam ao evento de teclado “pressionar a tecla TAB”, que movia o foco entre os botões, mas ao pressionar ENTER, nada acontecia. Isso porque só foram ligados cliques de mouse, não eventos de teclado, aos botões. Neste programa nós iremos ligar também alguns eventos de teclado aos botões. 19

P E N S A N D O E M T K I N T E R (1)(2) As linhas para ligar eventos de teclado aos botões são bem simples – elas têm o mesmo formato que aquelas que ligam eventos de mouse. A única diferença é que o nome do evento agora é o nome de um evento de teclado (neste caso, <Return^2 >). Quando queremos que a tecla ENTER ou um clique no botão esquerdo do mouse tenham o mesmo efeito no widget, ligamos o mesmo alimentador de eventos a ambos eventos. Este programa mostra que você pode ligar vários tipos de eventos a um único widget (como um botão), ou mesmo ligar várias combinações de widgets a um mesmo alimentador de eventos. (3)(4) Agora que nossos botões respondem a vários tipos de eventos, podemos demonstrar como receber informações de um objeto evento. O que vamos fazer é passar o objeto evento para (5) a rotina report_event que irá (6) imprimir uma informação sobre o evento, obtida a partir dos atributos do evento. Perceba que para vermos estas informações impressas na tela, é necessário rodar o programa usando python (nunca pythonw – como IDLE). Comportamento do programa Quando você roda o programa, vê dois botões. Clicando no botão da esquerda, ou pressionando ENTER quando o foco estiver neste botão, a sua cor será mudada. Clicando no botão direito, ou pressionando ENTER quando o foco estiver neste botão, a aplicação será fechada. Para qualquer um desses eventos de mouse ou teclado, você deverá ver uma mensagem impressa na tela informando a hora e descrevendo o evento. from Tkinter import * class MyApp: def init(self, parent): self.myParent = parent self.myContainer1 = Frame(parent) self.myContainer1.pack() self.button1 = Button(self.myContainer1) self.button1.configure(text="OK", background= "green") self.button1.pack(side=LEFT) self.button1.focus_force() ### (0) self.button1.bind("", self.button1Click) self.button1.bind("", self.button1Click) ### (1) self.button2 = Button(self.myContainer1) self.button2.configure(text="Cancel", background="red") self.button2.pack(side=RIGHT) self.button2.bind("", self.button2Click) (^2) Os americanos chamam a tecla ENTER de RETURN, daí o evento de teclado “pressionar ENTER” receber a sintaxe . (Nota do Tradutor) 20