如何在我的SWT应用程序中检测Ctrl + F?

12

我编写了一个 SWT UI,主要功能是在 StyledText 控件中显示文本。我想添加一个处理程序,当按下 Ctrl+F 快捷键时,将焦点设置到搜索框中。我尝试使用以下代码来检测按键。

sWindow = new Shell();
...
sWindow.getDisplay().addFilter(SWT.KeyDown, new Listener()
{
  @Override
  public void handleEvent(Event e)
  {
    System.out.println("Filter-ctrl: " + SWT.CTRL);
    System.out.println("Filter-mask: " + e.stateMask);
    System.out.println("Filter-char: " + e.character);
  }
});

我原本期望在按下 Ctrl+f 后能够看到以下输出:

Filter-ctrl: 262144
Filter-mask: 262144
Filter-char: f

然而,在实践中我看到了以下情况。

Filter-ctrl: 262144
Filter-mask: 262144
Filter-char: <unprintable char - displayed as a box in eclipse console>

我有两个问题:

  • Display.addFilter(...) 是添加全局快捷键的最佳方式吗?我尝试了 Display.addListener(...),但是这根本没有接收到任何事件。
  • 为什么当我按住 Ctrl 键时,我没有得到按下的字符?当我按住 alt 或 shift 时,我得到了预期的掩码和按下的字符。
1个回答

34

Display.addFilter(...)是否是添加全局快捷方式的最佳方法?我尝试过Display.addListener(...),但根本没有接收到任何事件。

是的,通常情况下Display.addFilter(...)是添加全局快捷方式的最佳方法,因为它们比事件侦听器具有更高的优先级。请参见以下来自Display.addFilter(...) javadoc的评论:

由于事件过滤器在其他监听器之前运行,因此事件过滤器可以阻止其他监听器并在事件中设置任意字段。因此,事件过滤器既强大又危险。出于性能、调试和代码维护等原因,应该避免使用它们。


至于您的第二个问题:

当我按住ctrl时,为什么无法获取按下的字符?当我按住alt或shift时,我得到了预期的掩码和按下的字符。

问题在于您正在查看错误的位置。您应该使用e.keyCode而不是查询e.character。根据e.character的javadoc,您不会仅获得字符f

取决于事件,表示键入的键的字符。这是所有修改器应用后产生的最终字符。例如,当用户键入Ctrl+A时,字符值为0x01(ASCII SOH)。

因此,当您按下CTRL+f时,它会转换为0x06(ASCII ACK)。而当您按下ALT+f SHIFT+f时,则不是这种情况。

另一方面,e.keyCode的javadoc说:

取决于事件,被键入的键的键代码,由类SWT中的键代码常量定义。当事件的字符字段不明确时,该字段包含原始字符的未受影响的值。例如,键入Ctrl+M或Enter都会导致字符'\ r',但是当键入Enter时keyCode字段还将包含'\ r',当键入Ctrl + M时,keyCode字段将包含'm'。

请查看下面的代码以获取更多详细信息。我尝试在DisplayTest上放置侦听器进行演示。

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public class ControlF 
{
    public static void main(String[] args) 
    {

        Display display = new Display ();

        final Shell shell = new Shell (display);
        final Color green = display.getSystemColor (SWT.COLOR_GREEN);
        final Color orig = shell.getBackground();

        display.addFilter(SWT.KeyDown, new Listener() {

            public void handleEvent(Event e) {
                if(((e.stateMask & SWT.CTRL) == SWT.CTRL) && (e.keyCode == 'f'))
                {
                    System.out.println("From Display I am the Key down !!" + e.keyCode);
                }
            }
        });

        shell.addKeyListener(new KeyListener() {
            public void keyReleased(KeyEvent e) {
                if(((e.stateMask & SWT.CTRL) == SWT.CTRL) && (e.keyCode == 'f'))
                {
                    shell.setBackground(orig);
                    System.out.println("Key up !!");
                }
            }
            public void keyPressed(KeyEvent e) {
                if(((e.stateMask & SWT.CTRL) == SWT.CTRL) && (e.keyCode == 'f'))
                {
                    shell.setBackground(green);
                    System.out.println("Key down !!");
                }
            }
        });

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

    }
}

1
这是一个非常好的答案 - 我现在已经让我的快捷方式工作了。谢谢!下次我会尽力自己更好地阅读文档! - mchr
我们该如何通过添加过滤器来覆盖系统快捷键,比如Ctrl+C? - Fahad
1
@Fahad - 建议您将其作为一个单独的问题提出。 - Favonius
请问如何在我的 SWT 应用程序中检测 Ctrl+F 快捷键? - Richard EB
1
注意:对于Mac电脑,如果您想考虑command+<key>事件,则需要包含SWT.COMMAND键事件的情况。 - Ben Holland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接