SWT Shell KeyListener

GGr*_*rec 5 java swt javafx jface eclipse-rcp

1.)目标

OSX的文件快速预览小部件.基本上,在Mac上,当您选择文件并按空格键时,您可以快速预览该文件.我正在尝试使用SWT + JFace(mmmaybe JavaFX)复制该功能.

Shell对我来说很合适.

Mac快速预览截图


2.)具体细节

  • 预览小部件将APPLICATION_MODAL Shell附加到StructuredViewer.

  • Shell每次打开预览时我都不想重新创建.我只想隐藏它.这应该是一个快速预览.

  • 我希望能够关闭这个ShellESCSPACE.

  • 我处理许多类型的文件(PDF,JPEG,PNG,TXT等),因此每个文件都有自己的预览组件.该Shell知道如何将这些组件之间进行切换.

  • 此组件可能无法修改任何文件,只需预览它们即可.我用来构建预览的组件是另一个故事.


3.)问题

  • 由于Shell有直接的孩子,这些孩子可能会"偷"焦点并抓住KeyEvents.因此,Shell不知道如何关闭键盘事件.

  • 我不想添加Display过滤器.每次显示/隐藏时,我都必须添加/删除它们Shell.另外,这些是非常危险的,因为它是一个巨大的RCP应用程序,它可能会影响其他工作台部件(如果由于某种原因没有删除过滤器).


4.)SSCCE

在下面的示例中,您可以观察到一旦Text具有焦点,Shell就无法抓回焦点,并且不会再将键事件泵入其中.

/**
 * 
 * @author ggrec
 *
 */
public class SSCCE_ShellWithShellParent
{

    // ==================== 1. Static Fields ========================

    private static final int CHILD_SHELL_STYLE = SWT.BORDER | SWT.RESIZE | SWT.TITLE | SWT.CLOSE | SWT.APPLICATION_MODAL;


    // ==================== 3. Static Methods ====================

    public static void main(final String[] args)
    {
        new SSCCE_ShellWithShellParent();
    }


    // ==================== 4. Constructors ====================

    private SSCCE_ShellWithShellParent()
    {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());

        final Shell childShell = new Shell(shell, CHILD_SHELL_STYLE);
        childShell.setLayout(new FillLayout());
        childShell.pack();

        createChildContents(childShell);

        final KeyAdapter keyListener = new KeyAdapter()
        {
            @Override public void keyPressed(final KeyEvent e)
            {
                final Object source = e.getSource();

                if (source == shell)
                    System.out.println(e.keyCode);
                else
                    System.err.println(e.keyCode);

                // Escape
                if (e.keyCode == 27)
                    shell.close();

                // Spacebar
                if (e.keyCode == 32 && e.getSource() == shell)
                    childShell.open();
            }
        };

        childShell.addKeyListener(keyListener);
        shell.addKeyListener(keyListener);

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


    // ==================== 5. Creators ====================

    private void createChildContents(final Shell childShell)
    {
        new Text(childShell, SWT.NULL);
    }

}
Run Code Online (Sandbox Code Playgroud)

5.)TL; DR

KeyListenerShell不使用过滤器的情况下添加.

小智 0

我有你的第一个问题的答案。你可以:

  • 使用以下方法删除 shell 子级的焦点能力 WHATEVER_CHILD.setFocusable(false);

  • 通过添加焦点监听器,使 shell 每次失去焦点时都请求焦点: YOUR_SHELL.addFocusListener(new FocusListener{ public void focusLost(FocusEvent e) { YOUR_SHELL.requestFocusOnWindow(); } });

我个人更喜欢第二种选择。