我很难理解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方法,这不是我期望的关键监听器!
答案 0 :(得分:1)
您要观察的是事件中的其他字段:
当时键盘修改键和鼠标掩码的状态 事件已经生成。
取决于事件,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 )
} );