[Rio-pm] Tecla pressionada

Marcos Machado listas em istf.com.br
Terça Março 4 11:50:02 PST 2008


Bom, acabei encontrando algo que me atende bem. O código abaixo mostra a 
tecla pressionada e a tecla solta.

Um efeito que não previa é a possibilidade de saber quando uma "tecla 
cinza" é pressionada como, por exemplo, o shift, coisa que não é 
possível lendo pelo terminal.

Pode parecer óbvio para quem já programou nesse ambiente. Para mim é 
tudo novidade. :)

<code>
use Tk;
$top = MainWindow->new();
$frame = $top->Frame( -height => "2c", -width => "2c" );
$frame->pack;
$top->bind("<Any-KeyPress>" =>
sub
{
     my $c = shift;
     my $e = $c->XEvent;
     print "Pressionada = ", $e->K, "$/";
});
$top->bind("<Any-KeyRelease>" =>
sub
{
     my $c = shift;
     my $e = $c->XEvent;
     print "Liberada = ", $e->K, "$/";

});
MainLoop();
</code>

Se quiser testar um evento de "release" de tecla mais longo, execute 
antes o comando "xset -r" para desligar a repetição da tecla quando ela 
é pressionada por muito tempo.

Obs: Logo percebe-se que Ctrl+C é inútil para encerrar o programa. 
Fechar a janelinha que ele abre é o suficiente.

[]s, MM



Fernando Oliveira escreveu:
> será q vc não pode fazer algo parecido com isso?:
> <code>
> use Term::ReadKey;
> 
> ReadMode 4;
> while (($key = ReadKey(-1)) ne "q") {for(keys %time){delete $time{$_} if 
> time - $time{$_} > $vezes}next unless defined 
> $key;$time{$key}=time,$vezes=1 unless defined $time{$key};delete 
> @time{grep {$_ ne $key} keys %time}; $vezes++ if time - $time{$key} <= 
> $valor;delete $time{$key}, undef $vezes, print "$key foi pressionado por 
> 5 segundos$/" if time - $time{$key} == 5}END{ReadMode 0;}
> </code>
> 
> Em 19/02/08, *Marcos Machado* <listas em istf.com.br 
> <mailto:listas em istf.com.br>> escreveu:
> 
>     Hmmmm... Obrigado pela luz!
> 
>     Vou experimentar estas idéias.
> 
>     O fato de precisar mapear uma tecla específica com um evento é ruim,
>     pois não sei o que será pressionado e, em qualquer tecla, a rotina
>     executada é a mesma.
> 
>     Outra coisa que me preocupa é o processamento intrínseco destas
>     bibliotecas ou do próprio ambiente. O tempo que a tecla vai ficar
>     pressionada é muito, muito pequeno (imagina o tempo que cada tecla fica
>     pressionada enquanto você digita um texto) e vai complicar se ficarmos
>     muito dependente do processamento da máquina para me dar esse valor.
> 
>     Mas vou fazer uns testes e volto com o resultado.
> 
>     []s, MM
> 
> 
>     breno escreveu:
>      > Em Mac, seria assim:
>      >
>      > -----------------8<--------------------
>      > use Mac::Events qw(@Event $CurrentEvent);
>      >
>      > $Event[keyDown] = \&trata_tecla_apertada;
>      > $Event[keyUp]     = \&trata_tecla_solta;
>      > -----------------8<--------------------
>      >
>      > E no Windows dá pra fazer assim:
>      > -----------------8<--------------------
>      > use Win32::Console;
>      >
>      > $CONSOLE = new Win32::Console->new(STD_INPUT_HANDLE);
>      >
>      > do {
>      >    @event = $CONSOLE->Input();
>      >    # [0] : tipo de evento (1 para teclado)
>      >    # [1] : keydown (TRUE == tecla apertada, FALSE == tecla foi solta)
>      >    # [2] : número de vezes que o Input retornou a tecla como
>     ainda apertada
>      >    # [3] : virtual key code da tecla
>      >    # [4] : virtual scan code da tecla
>      >    # [5] : código ASCII do caractere apertado (ou 0 se nao for
>     caractere)
>      >    # [6] : estado das teclas de controle (CTRL ALT SHIFT)
>      >
>      >    # processa tecla enquanto está apertada
>      >    ...
>      >
>      > } while ($event[0] == 1 and $event[1]);
>      > -----------------8<--------------------
>      >
>      > E em SDL:
>      > -----------------8<--------------------
>      > use SDL::Event;
>      >
>      > my $event = new SDL::Event;
>      > $event->pump;
>      > $event->poll;
>      >
>      > if ( $event->type == SDL::KEYDOWN ) {
>      >     # tecla pressionada. Pra saber qual tecla, basta adicionar aqui:
>      >     if ( $event->key_sym == SDLK_ESCAPE ) {  # ou qq outra, brincando
>      > com key_sym
>      >         ...
>      >     }
>      > }
>      > if ( $event->type == SDL::KEYDOWN ) {
>      >     # idem
>      > }
>      > -----------------8<--------------------
>      >
>      > Mas direto num terminal linux.... não sei =P
>      >
>      > Provavelmente a obtenção de eventos tipo keydown/keyup esteja
>      > disponível amarrada a algum loop de eventos (já que a shell em si é,
>      > por padrão, orientada a stream de caracteres e não a eventos). Dentro
>      > do X é muito fácil (pois é um ambiente baseado em eventos), e qq
>      > biblioteca como Tk, GTK, Wx, ou mesmo acesso X "rawzão" resolve o seu
>      > problema. Pra terminal, loops de eventos pré-prontos podem te ajudar
>      > em sua saga. Nunca usei POE, mas ele é um que pode ter o que vc quer.
>      > E, se não me falha a memória, o Curses também tem (resta saber se a
>      > implementação do Curses.pm <http://Curses.pm> está completa em
>     relação à bilbioteca, já
>      > que a documentação deles foi bem preguiçosa).
>      >
>      > Não deixe de nos avisar sobre sua solução :-)
>      >
>      > []s
>      >
>      > -b
>      >
>      > 2008/2/19 Marcos Machado <listas em istf.com.br
>     <mailto:listas em istf.com.br>>:
>      >> Caros monges,
>      >>
>      >> Estou procurando uma forma de identificar uma tecla pressionada. O
>      >> exemplo abaixo me diz, tecla a tecla, o que foi digitado, sem
>     precisar
>      >> esperar o <Enter>.
>      >>
>      >> <code>
>      >> use Term::ReadKey;
>      >> open(TTY, "</dev/tty");
>      >> ReadMode "raw";
>      >> while (ord $key != 10) # 10 = return/enter
>      >> {
>      >>      $key = ReadKey 0, *TTY;
>      >>      print "Voce pressionou a tecla $key (",ord $key,")", $/;
>      >> }
>      >> ReadMode "normal"; # restaura modo normal de leitura
>      >> </code>
>      >>
>      >> Agora gostaria de descobrir por QUANTO TEMPO uma tecla se manteve
>      >> pressionada. Este método me tira da linha 6 assim que eu pressiono a
>      >> tecla. Preciso de um evento quando a tecla é pressionada e outro
>     quando
>      >> ela é solta.
>      >>
>      >> Alguma dica?
>      >>
>      >> Não precisa ser portável. Funcionando em Linux já tá bom demais.
>      >>
>      >> Obrigado pela atenção.
>      >>
>      >> []s, MM
>      >> _______________________________________________
>      >> Rio-pm mailing list
>      >> Rio-pm em pm.org <mailto:Rio-pm em pm.org>
>      >> http://mail.pm.org/mailman/listinfo/rio-pm
>      >>
>      > _______________________________________________
>      > Rio-pm mailing list
>      > Rio-pm em pm.org <mailto:Rio-pm em pm.org>
>      > http://mail.pm.org/mailman/listinfo/rio-pm
>      >
> 
>     _______________________________________________
>     Rio-pm mailing list
>     Rio-pm em pm.org <mailto:Rio-pm em pm.org>
>     http://mail.pm.org/mailman/listinfo/rio-pm
> 
> 
> 
> 
> -- 
> []'s Fernando
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Rio-pm mailing list
> Rio-pm em pm.org
> http://mail.pm.org/mailman/listinfo/rio-pm



Mais detalhes sobre a lista de discussão Rio-pm