SWT.KeyUp过于频繁地触发

时间:2015-12-01 10:18:29

标签: java swt keylistener

我很难理解SWT中的关键事件。我的程序在Windows 8.1 + Java 8下运行 例如,我有一个文本字段,并尝试处理KeyUp:

textField.addListener(SWT.KeyUp, new Listener() {
  @Override
  public void handleEvent(Event e) {
  }
});

在handleEvent方法中,我将e.doit设置为false,然后我尝试区分箭头键,空格键或ALT +字母等的某些组合。

我有点疑惑,因为我的应用程序执行的不是正确的任务。所以我调试了coe并发现handleEvent方法每次都使用不同的事件对象执行三次 这并不好,因为在这种情况下,几乎不可能以预期的方式使其工作 - 每次调用都可以取代f.e.前一次通话的属性值 我不知道原因:我按一个键,处理程序方法被调用三次。为什么?这对我来说有点不合逻辑......

+++ EDITED +++

package mytest;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class Main {
  private static int i = 0;

  public static void main(String[] args) {
    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setLayout(new FillLayout());
    Text textField = new Text(shell, SWT.BORDER | SWT.READ_ONLY | SWT.SINGLE);
    textField.addListener(SWT.KeyUp, new Listener() {
      @Override
      public void handleEvent(Event e) {
        e.doit = false;
        System.out.println("Call #" + (++i) + ": keyCode=" + e.keyCode);
      }
    });

    shell.pack();
    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch())
        display.sleep();
    }
    display.dispose();
  }
}

你可以运行这个小例子,然后按f.e. ALT + A,CTRL + I或ARROW_DOWN你会发现每次按下时都会调用handle方法,这不是我期望的关键监听器!

2 个答案:

答案 0 :(得分:1)

解决方案

您要观察的是事件中的其他字段:

stateMask

  

当时键盘修改键和鼠标掩码的状态   事件已经生成。

keyLocation

  

取决于事件,keyCode指定的密钥的位置   或者角色。此字段的可能值为SWT.LEFT,   SWT.RIGHT,SWT.KEYPAD或代表主键盘的SWT.NONE   区域。

     

位置字段可用于区分关键事件   具有相同的密钥代码和字符,但由不同的生成   键盘上的键。例如,带有密钥代码的按键事件   等于SWT.SHIFT可以通过左右移动生成   键盘上的按键。

     

位置字段只能用于确定位置   当前事件中的关键代码或字符。它不包括   有关状态掩码中修饰符位置的信息。

更新示例

正确的,预期的行为是,每个密钥都会被释放,您会收到通知。用以下内容替换问题中的println:

System.out.println("Call #" + (++i) + ": keyCode=" + e.keyCode + " stateMask=" + e.stateMask
        + " ctrlPressed=" + ((e.stateMask & SWT.CTRL) != 0) + " shiftPressed="
                + ((e.stateMask & SWT.SHIFT) != 0)+ " altPressed="
                        + ((e.stateMask & SWT.ALT) != 0));

你应该观察到正确的行为。 stateMask详细说明了状态(例如按下了控制键)。

使用额外的打印更新代码,这是您在控制台中看到的内容:

代表 a

Call #11: keyCode=97 stateMask=0 ctrlPressed=false shiftPressed=false altPressed=false

对于 ctrl + a ,先发布 a

Call #14: keyCode=97 stateMask=262144 ctrlPressed=true shiftPressed=false altPressed=false
Call #15: keyCode=262144 stateMask=262144 ctrlPressed=true shiftPressed=false altPressed=false

对于 ctrl + a ,先发布 ctrl

Call #16: keyCode=262144 stateMask=262144 ctrlPressed=true shiftPressed=false altPressed=false
Call #17: keyCode=97 stateMask=0 ctrlPressed=false shiftPressed=false altPressed=false

对于 ctrl + shift + alt + a ,其中 a 已发布第一:

Call #19: keyCode=97 stateMask=458752 ctrlPressed=true shiftPressed=true altPressed=true
Call #20: keyCode=65536 stateMask=458752 ctrlPressed=true shiftPressed=true altPressed=true
Call #21: keyCode=131072 stateMask=393216 ctrlPressed=true shiftPressed=true altPressed=false
Call #22: keyCode=262144 stateMask=262144 ctrlPressed=true shiftPressed=false altPressed=false

为什么?

如果只按 ctrl 键,则有很多地方需要知道。考虑将鼠标悬停在Eclipse中的方法或变量上并按下/释放 ctrl

更新

根据评论中提供的其他信息,OP希望允许用户创建加速器。

jface,SWT顶部的图层已经有KeySequenceText类(代码:in git),

  

围绕SWT文本小部件的包装器,用于捕获文字按键   并将它们转换为关键序列以供显示。有两种类型   显示的击键次数:完整和不完整。一套完整的   击键是一个有自然键,而一个不完整的有没有   自然的关键。不完整的击键只会显示   完成或他们的组件按键被释放。

显然我建议重复使用它而不是旋转一个新的。它只是很少使用1000行代码,因此可能已经很好地运用了,并且(大部分都是)没有bug。

由于您在Eclipse平台之外使用SWT,如果您确实想采用这种方法,也可以使用jface outside the platform

答案 1 :(得分:-2)

通常在每次呼吸时都会非常频繁地调用添加了addListener的侦听器。对于关键事件,请使用

textField.addKeyListener( new KeyAdapter() 
{ 
   public void keyPressed( Event e ) 
} );