Capítulo 4

Diálogos são interessantes para introduzir uma resposta simples do usuário, ou para confirmar uma operação que está para ser realizada. Alguns comandos pré-definidos do tk nos fornecem os diálogos mais comuns, bem como browsers de arquivos e cores, como também para criar menus popup: tk_dialog, tk_messageBox, tk_getOpenFile, tk_getSaveFile, tk_chooseColor, tk_optionMenu, tk_popup. Estes comandos são simplesmente scripts localizados no diretório reservado para a biblioteca do tk, normalmente /usr/local/lib/tk8.0. Entretanto, como estes comandos criam novos toplevels quando executados, não é possível mostrá-los como tclets, voce terá que executá-los em seu próprio ambiente.

Até agora vimos GUIs criadas só visualmente com o visual tcl, mas agora que voce já está se familiarizando com os widgets do tcl/tk, tenho uma boa nova: para cada widget, existe um comando que cria um widget, sem a necessidade desse editor visual. E o melhor é que este comando é o nome do próprio widget! Por exemplo, para criar um botão, usamos o comando button, para criar um frame, o comando frame, e assim por diante. Os atributos desses widgets têm exatamente os nome encontrados no visual tcl, mas como são opções do comando, são representados com um hífen "-" prefixando-os. Vejamos, como exemplo, como criar um botão que, ao pressionado, imprima na console (que o executou) a famosa mensagem "Alô mundo!":

button .b -text Alô -command {puts "Alô mundo!"}

Observe atentamente o código gerado pelo visual tcl quando voce salva uma interface. Ela conterá uma série de comandos como esse para cada widget criado.

tk_dialog O tk pode produzir diálogos modais, com bitmaps a serem escolhidos pelo programador, mensagens e botões. O diálogo ao lado foi criado com o comando:
tk_dialog .dlg "Exemplo de diálogo" \
  "Este é um diálogo simples, \
  utilizando tk_dialog, \
  pré-definido pelo Tk." info 0 OK 

Um diálogo que nos fornece um "file browser", com seleção de tipos de arquivos definíveis pelo programador, "file default", extensão default, etc., chamado tk_getOpenFile. O diálogo complementar tk_getSaveFile fornece propriedades semelhantes para nomes de arquivos a salvar. tk_getOpenFile

Podemos dispensar completamente os editores visuais definindo os nossos widgets como acima, mas como fazer com que um script editado seja um programa executável? Felizmente, no Linux (como em outros Unices), é possível transformar um script em qualquer linguagem num executável, iniciando o script por uma sequência "mágica". Esta mágica consiste em por na primeira linha do arquivo a string "#!" seguida do comando a executar. Assim, se colocarmos "#!/usr/local/bin/wish" na primeira linha do nosso arquivo, ele será executado como fonte para o programa /usr/local/bin/wish (interpretador tcl com o tk). O problema que resta nessa versão simplificada, é que o interpretador wish pode estar em outro lugar, mas no PATH. Com um pouco de ingenuidade resolvemos esse problema, usando o fato que um comentário em tcl pode ser estendido a mais de uma linha, se a linha termina com uma barra invertida "\". A receita parece complicada, mas basta copiar em cada programa tcl/tk que desejarmos:

#!/bin/sh
# \
exec wish "$0" "$@"

e assim nosso wish pode estar em qualquer diretório no path.

Nosso primeiro exemplo usa dois widgets, uma mensagem (message) na parte superior e uma entrada (entry) na parte inferior, arrajados com o pack. Inicialmente definimos os dois widgets, fornecendo os parâmetros desejados. No caso da mensagem, o texto (opção -text) que será mostrado. No caso da entrada, uma variável associada (com o atributo -textvariable), que será mostrada nesse widget, quando for modificada. Eventualmente, uma entry é usada mais para entrada de dados, mas ela se presta bem ao que queremos mostrar.

Para arranjar e visualizar os widgets, usamos o pack, com opções para manter um espaçamento externo em cada widget de 5 pixels na direção x e 10 na direção y. Estas opções são -padx e -pady. De outra forma os widgets gerenciados pelo pack ficariam "colados" um no outro, sem espaço entre eles, ou entre eles e a borda externa do toplevel.

Nossa aplicação irá mostrar um menu popup, criado pelo comando tk_optionMenu, que conterá nomes de algumas frutas que queremos que o usuário escolha. O comando tk_optionMenu espera como argumentos: nome do widget (menubutton) a ser criado, nome da variável onde armazenar a seleção, e demais argumentos são as opções do menu. Devemos salvar o menu retornado numa variável para chamá-lo posteriormente. Poderíamos também mapear o menubutton criado diretamente, usando o pack ou outro gerenciador de geometria.

Finalmente, definiremos um binding (comando bind) para toda a janela (usando o toplevel "." } quando o evento desejado ocorrer. Para representar um evento "botão de mouse", usamos o númreo deste botão entre "<" e ">". O próximo argumento é um comando que deverá ser executado quando as condições desse binding forem satisfeitas. Aí entra o comando tk_popup, para mostrar o nosso menu. Ele espera como argumentos o menu e a posição x e y aonde deverá ser mostrado o menu. Faremos o nosso menu "aparecer" no local aonde o mouse foi clicado. Obtemos essa posição com o comando winfo pointerx . (para a coordenada x), e similarmente para a coordenada y.

#!/bin/sh
# A linha seguinte executa o interpretador \
exec wish "$0" "$@"

message .msg -text { Clicando o botão 1 do mouse \
nesta janela, voce verá um menu com vários \
radiobuttons, criado com o comando \ 
tk_optionMenu e invocado com tk_popup.
A entry abaixo mostrará o valor \
corrente da variável "fruta" \
selecionada.}

entry .fruta -textvariable fruta
pack .msg .fruta -padx 5 -pady 10

set fmenu [tk_optionMenu .mfru fruta \
   manga goiaba banana uva]
bind . <1> { tk_popup $fmenu \
   [winfo pointerx .] [winfo pointery .] }
optmenu

Infelizmente, esse programa não funciona como tclet, pois utiliza menus, o que seria uma quebra de segurança, como discutimos anteriormente. Salve o código ao lado em um arquivo e execute-o diretamente (não esqueça primeiro "chmod +x arquivo") ou via "wish arquivo".

Experimente usar o menubutton criado suprimindo o comando bind e fazendo:

   pack .mfru

selecione as opções (frutas) e veja o que acontece com a legenda no botão.

bindings

Podemos adicionar comportamento na forma de respostas a eventos a qualquer objeto de nossa interface. Um exemplo é o resultado do comando bind acima, em resposta ao evento botão de mouse <1>. Em geral, temos uma sequência de eventos invocando um comando, na forma genérica: bind tag sequência comando. O tag pode representar uma instância de um widget, como no exemplo acima, fornecendo o nome explícito do widget; ou pode ser toda uma classe, por exemplo Frame, Button, Label, etc, quando definimos o nome da classe de objetos (widgets) com a primeira letra maiúscula; ou ainda a palavra all, representando todos as janelas (widgets) da aplicação. A sequência pode ser o número de um botão do mouse, uma tecla, ou eventos especiais como Activate, Circulate, Colormap, Configure, Deactivate, Destroy, Enter, Expose, FocusIn, FocusOut, Gravity, Motion, Leave, Map, Property, Reparent, Unmap, Visibility, representando eventos gerados pelo sistema de janelas X com relação às janelas. Estes eventos podem ser prefixados por modificadores que indicam situações, como espécie de filtros, sob as quais os eventos são válidos, tais como: Control, Shift, Lock, Alt, Meta, Double, Triple. Por exemplo, <Control-1> define o evento "botão do mouse 1 cvom tecla Control pressionada", <Double-Alt-2> define "dois cliques no botão do meio do mouse com a tecla Alt pressionada", <Shift-Enter> define o evento "entrando no widget com a tecla Shift pressionada" e assim por diante. Algumas teclas têm nomes especiais, como Return (não exatamente o Enter usado pelo MS-Windows), Backspace, Shift_L, Insert, Delete, Prior, Next. Use o programa abaixo para descobrir todos os nomes ou consulte o arquivo /usr/include/X11/keysymdef.

O tclet ao lado é um simples text com os bindings alterados para nos mostrar alguns eventos que podem ocorrer. Quando "entramos" no widget, o Enter, quando saimos o Leave, cada botão do mouse pressionado ou liberado, e teclas. Experimente! Veja também que algumas teclas têm nomes especiais, como o Shift, Control e Alt. No comando usamos %K para obter esses nomes.


rpragana Mon Mar 22 10:40:12 EST 1999