[Rio-pm] Tecla pressionada

breno breno em rio.pm.org
Terça Março 4 12:05:57 PST 2008


É.... como eu disse, fazer código em cima de um loop de eventos no X
resolve o problema facilmente, mas eu usaria SDL e não Tk :-)

De qq forma, achei que vc precisasse que o prog rodasse apenas no
terminal - essa ainda fica sem solução, com a resposta mais próxima
sendo a do Fernando mesmo.

[]s

-b

2008/3/4 Marcos Machado <listas em istf.com.br>:
> 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
>
>  _______________________________________________
>  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