Событие JAVA SWT KeyDown сработало 3 раза вместо одного при переключении с SWT 3 на SWT 4 - PullRequest
0 голосов
/ 03 ноября 2019

Меня озадачивает следующая проблема: у меня есть приложение SWT Java, и переключение с SWT 3 на SWT 4 приводит к странному поведению события KeyDown при следующих обстоятельствах:

У меня есть одна оболочка, содержащая браузервиджет. Я слушаю события KeyDown на уровне Java через фильтр объекта Display, как показано ниже. Когда такое событие обнаружено, я затем вызываю функцию execute () виджета Browser для выполнения некоторого JavaScript. Я выбрал обнаружение события KeyDown на глобальном уровне Java, а не непосредственно в javascript, потому что браузер может не обязательно фокусироваться в этот момент.

Ожидаемое поведение: событие KeyDown должно обнаруживаться один раз

Фактическое поведение: событие KeyDown обнаруживается три раза

То, что я пробовал и изучил до сих пор: 1) Проблема возникает только при использовании виджета «Браузер». 2) Проблема возникает не только при выполнении некоторого JavaScript, но также и в том случае, если я просто устанавливаю содержимое браузера (br.setText ("...")), поэтому кажется, что любое действие в браузере вызывает проблему. 3) Проблема не возникает с SWT 3.836. Это происходит с SWT 4.924

Возврат к SWT 3 не идеальный вариант, потому что он вызвал много сбоев из-за libwebkitgtk, и я избавился от них с SWT 4 ...

Конфигурация: Ubuntu 18.04, Java openjdk 11 adm64, SWT 4.924 (загружено со страницы загрузки Eclipse последняя стабильная версия 4.14M1)

Вот код:

public static void main(String[] args) {
    System.out.println("Launching test application");

    Display display = new Display();
    Shell shell = new Shell(display);

    Browser br = new Browser(shell,SWT.NONE);
    br.setSize(500,500);

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

        @Override
        public void handleEvent(Event event) {
            System.out.println(event.keyCode);
            //Try either of the following two lines to reproduce the problem. If you comment both lines, the problem disappears
            br.execute("javascript:alert('hello')");
            //br.setText("<html><head></head><body>TEST</body></html>");
        }
    });

    shell.open();

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

Есть подсказки? Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 04 ноября 2019

Быстрый и грязный способ справиться с этим - подсчитать количество событий и число их 2 в каждых 3, например так:

display.addFilter(SWT.KeyDown, new Listener() {
        int i = 0;
        @Override
        public void handleEvent(Event event) {

            if (i<2) {
                i++;
            }else {
                System.out.println(event.keyCode);
                i=0;
            }
        }
    });

`Однако, чтобы это работалоМне нужно быть на 100% уверенным, что событие будет систематически вызываться 3 раза, как, по крайней мере, в моем упрощенном примере и в моей собственной конфигурации.

Я думаю, что собираюсь использовать что-то вродечто в то же время, но все же было бы хорошо, чтобы в конечном итоге добраться до сути этого.

0 голосов
/ 03 ноября 2019

Я протестировал ваш код на Windows 10 и SWT 4.924 и получаю событие 2 раза.

Я предполагаю, что Browser также взаимодействует с фильтром, вызывая несколько событий (см. Этостарый комментарий, не уверен, если связан: https://bugs.eclipse.org/bugs/show_bug.cgi?id=69919#c8).

Также кажется, что проблема возникает только тогда, когда Browser имеет фокус, и работает правильно, когда какой-то другой элемент управления имеет фокус.

Таким образом, в качестве обходного пути, вы можете использовать фильтр, когда браузер не имеет фокуса, в противном случае стандартный слушатель ключа на Browser, когда он имеет.

Например:

br.addKeyListener(keyPressedAdapter(event -> {
    handleBrowserKeyEvent(br, event.keyCode);
}));

display.addFilter(SWT.KeyDown, new Listener() {
    @Override
    public void handleEvent(Event event) {
        // when the browser has focus, use his key listener instead of this filter 
        if (br.isFocusControl()) {
            return;
        }
        handleBrowserKeyEvent(br, event.keyCode);
    }
});

Где в handleBrowserKeyEvent вы поместили свою логику обработки.

Обратите внимание, что в моем случае мне также пришлось поставить shell.forceFocus(); сразу после shell.open();, иначе слушатель ключа браузера не сработал бы сразу(Не знаю почему).

...