2013-09-26 45 views
1

在Perl/Tk的,可以綁定一個像這樣的事件:如何在Perl/Tk中獲取密鑰的狀態?

$mw->bind('<KeyPress-W>', sub{print "W is pressed";}); 

是否有可能獲得此信息的另一個方向?我可以撥打電話「獲取密鑰的狀態」或「檢查W是否按下」嗎?

它不會直接對事件作出反應。

當然,有可能爲各種事件填充變量,但我想知道是否有這種方法。

+0

你可以綁定一個事件,在你的程序中設置一個控制標誌,但否則我不知道另一種方法。 – rutter

回答

3

Perl/Tk不提供這樣的功能。所以你必須自己跟蹤事件。請注意,是Any-KeyPressAny-KeyRelease事件,所以你不必創建每個鍵的綁定:

$mw->bind("<Any-KeyPress>" => sub { 
    warn $_[0]->XEvent->K; # prints keysym 
}); 

如果你在X11,然後使用X11::Protocol模塊(可內使用Perl/Tk腳本)並調用QueryKeymap方法會給你實際按下的鍵碼。這裏有一個腳本,它演示了這一點:

use strict; 
use X11::Protocol; 

# Get the keycode-to-keysym mapping. Being lazy, I just parse 
# the output of xmodmap -pke. The "real" approach would be to 
# use X11 functions like GetKeyboardMapping() and the 
# X11::Keysyms module. 
my %keycode_to_keysym; 
{ 
    open my $fh, "-|", "xmodmap", "-pke" or die $!; 
    while(<$fh>) { 
     chomp; 
     if (m{^keycode\s+(\d+)\s*=(?:\s*(\S+))?}) { 
      if (defined $2) { 
       $keycode_to_keysym{$1} = $2; 
      } 
     } else { 
      warn "Cannot parse $_"; 
     } 
    } 
} 

my $x11 = X11::Protocol->new; 
while(1) { 
    my $keyvec = $x11->QueryKeymap; 
    for my $bit (0 .. 32*8-1) { 
     if (vec $keyvec, $bit, 1) { 
      warn "Active key: keycode $bit, keysym $keycode_to_keysym{$bit}\n"; 
     } 
    } 
    sleep 1; 
}