自定义关键事件

Sou*_*are 6 java keyboard events swt keyevent

如何发送自定义SWT键事件,以便在不进行任何转换的情况下输入该确切的文字字符?

我们正在制作一个自定义的屏幕图形键盘,允许多种可能的布局 - QWERTY是主要的布局,但其他几个计划,包括可视化模拟iPhone键盘布局或其他相对于PC非标准的布局.

我希望能够将我选择的任意字符作为事件发送,这样就会导致输入该确切的字符.但是,每当我发送一个具有给定字符的事件时,SWT似乎会根据系统的键盘设置和状态自动解释和转换它,将其更改为大写/小写或使用移位的符号,具体取决于移位键(按下实际键盘上的真实键盘.例如,将字符'T'传递给键事件将导致't'或'T',具体取决于shift键.它的表现类似于'4'字符,根据班次做'4'或'$'.

这是有问题的,因为我希望手动执行字符移位,并且实际上可能不希望在任何给定情况下使用与标准QWERTY键盘相同的移位字符(例如,我可能希望'$'被移位(或'功能'键)版本的'R'在较小的手机式键盘上).我怎样才能使用这些事件,以免它假设使用QWERTY键?

SWT事件中"字符"字段的文档说明如下:

键入的键所代表的字符.这是应用所有修改器后生成的最终字符.例如,当用户键入Ctrl + A时,字符值为0x01.重要的是,应用程序不会尝试基于stateMask(例如SWT.CTRL)修改字符值,否则生成的字符将不正确.

这让我相信它不应该像我一样转换我的角色,因为我命令它使用我的"最终"结果.

我已经创建了一个简单的独立示例来演示我的问题(请注意,这不是我在做实际键盘的方式,而只是为了突出显示关键事件问题):

截图

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Button;

public class KeyboardIssueExample extends Shell {
    private Text txtTextArea;
    private Composite cmpButtons;
    private Button btnBigA;
    private Button btnBigS;
    private Button btnLittleD;
    private Button btnSix;
    private Button btnSeven;
    private Button btnDollah;
    private Button btnStar;

    private SelectionListener mainListener = new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent selE) {
            Button b = (Button)selE.widget;
            char c = b.getText().charAt(0);
            sendKey(c);
        }
    };

    /**
     * Launch the application.
     * @param args
     */
    public static void main(String args[]) {
        try {
            Display display = Display.getDefault();
            KeyboardIssueExample shell = new KeyboardIssueExample(display);
            shell.open();
            shell.layout();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Create the shell.
     * @param display
     */
    public KeyboardIssueExample(Display display) {
        super(display, SWT.SHELL_TRIM);
        createContents();
    }

    /**
     * Create contents of the shell.
     */
    protected void createContents() {
        setText("SWT Application");
        setSize(450, 300);
        setLayout(new GridLayout());

        txtTextArea = new Text(this, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);
        txtTextArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

        cmpButtons = new Composite(this, SWT.NONE);
        cmpButtons.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        GridLayout gl_cmpButtons = new GridLayout(7, false);
        gl_cmpButtons.marginWidth = 0;
        gl_cmpButtons.marginHeight = 0;
        cmpButtons.setLayout(gl_cmpButtons);

        btnBigA = new Button(cmpButtons, SWT.NONE);
        btnBigA.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        btnBigA.setText("A");

        btnBigS = new Button(cmpButtons, SWT.NONE);
        btnBigS.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        btnBigS.setText("S");

        btnLittleD = new Button(cmpButtons, SWT.NONE);
        btnLittleD.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        btnLittleD.setText("d");

        btnSix = new Button(cmpButtons, SWT.NONE);
        btnSix.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        btnSix.setText("6");

        btnSeven = new Button(cmpButtons, SWT.NONE);
        btnSeven.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        btnSeven.setText("7");

        btnDollah = new Button(cmpButtons, SWT.NONE);
        btnDollah.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        btnDollah.setText("$");

        btnStar = new Button(cmpButtons, SWT.NONE);
        btnStar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        btnStar.setText("*");

        init();
    }

    private void init() {
        btnBigA.addSelectionListener(mainListener);
        btnBigS.addSelectionListener(mainListener);
        btnLittleD.addSelectionListener(mainListener);
        btnSix.addSelectionListener(mainListener);
        btnSeven.addSelectionListener(mainListener);
        btnDollah.addSelectionListener(mainListener);
        btnStar.addSelectionListener(mainListener);
    }

    @Override
    protected void checkSubclass() {
        // Disable the check that prevents subclassing of SWT components
    }


    private void sendKey(char c) {
        sendKeyEvent(c, SWT.KeyDown);
        sendKeyEvent(c, SWT.KeyUp);
    }

    private void sendKeyEvent(char c, int eventType) {
        txtTextArea.forceFocus();
        Event event = new Event();
        event.type = eventType;
        event.character = c;
        getDisplay().post(event);
    }

}
Run Code Online (Sandbox Code Playgroud)

正如您将发现的那样,关键事件不尊重我自己对大小写的自定义使用,而是使用它自己的.多麻烦.

gre*_*449 4

查看Display.postMac 和 Windows 的源代码,有很多特定于向上/向下键事件的代码。这包括调用操作系统特定的 API,以将您指定的字符和按键代码转换为用于生成击键事件的操作系统特定方法所需的参数。

对于 Windows,此代码调用VkKeyScan根据 Microsoft 文档确实查看当前键盘状态。

Display确实有一个postEvent(Event)方法可以添加到事件队列而不更改任何内容,但这不是公开的,因此您必须使用反射来访问它。由于它不是官方 API 的一部分,因此可能会发生变化。

编辑:实际上这里有一个 Eclipse 错误报告。它已经开放了 10 年,所以可能不会被修复!

更新:还有一种Widget.notifyListeners(eventType, Event)方法可用于将按键事件发送到特定控件。您必须创建Event并设置必填字段。