[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