Сосредоточьтесь на проблемах с JDK7 и нативными компонентами

У нас есть приложение Swing, в которое встроен компонент IE ocx через JNIWrapper.

После перехода с jdk6 на jdk7 мы начинаем замечать проблемы с фокусировкой. Когда встроенный IE показывает веб-страницу с текстовыми полями (например, страницу поиска Google), начинаются проблемы:

Браузер «ловит» фокус, поэтому вы можете начать печатать в текстовом поле поиска. Каждый введенный ключ попадает в IE ocx. Но свинг, кажется, игнорирует это изменение фокуса. Даже если я сменю фокус на текстовое поле качания (и качание показывает мигающий курсор ввода), все набранные клавиши переходят в IE ocx

Единственный способ «зафиксировать» фокус — деактивировать и активировать основной кадр. после этого фокус кажется постоянным. Но если я снова нажму в текстовом поле поиска Google, фокус снова сломается.

Кажется, в jdk7 произошли большие изменения в обработке фокуса. По ссылке:

На платформе Windows реализована концепция «синтетического фокуса». Это означает, что компонент-владелец фокуса только эмулирует свое фокусируемое состояние, в то время как реальный собственный фокус устанавливается на компонент «прокси фокуса». Этот компонент получает собственные сообщения ключа и метода ввода и отправляет их владельцу фокуса. До JDK7 прокси-компонент фокуса был выделенным скрытым дочерним компонентом внутри фрейма/диалога. В JDK7 сам кадр/диалог служит прокси-сервером фокуса. Теперь он проксирует фокус не только для компонентов в собственном окне, но и для всех дочерних компонентов. Простое окно никогда не получает собственного фокуса и полагается на прокси фокуса своего владельца. Этот механизм прозрачен для пользователя, но его следует учитывать при отладке.

У кого-нибудь есть идея «исправить» поведение?

EDIT: вот код для воспроизведения проблемы с JxBrowser

    public static void main(String[] args) {
    Browser browser = BrowserFactory.createBrowser(BrowserType.IE);

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(browser.getComponent(), BorderLayout.CENTER);

    JPanel panel = new JPanel();
    frame.getContentPane().add(panel, BorderLayout.NORTH);

    textField = new JTextField();
    panel.add(textField);
    textField.setColumns(10);
    frame.setSize(700, 500);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    browser.navigate("http://www.google.com");
}

person mabr    schedule 19.04.2012    source источник
comment
может быть, я ошибаюсь, но это проблема с FocusRecycle, реализованным в Native OS, пожалуйста, как обращаться с вашей оболочкой с помощью Focus, toFront, в основном Java не заботится о событиях Mouse & Key без Focusable   -  person mKorbel    schedule 19.04.2012
comment
мы могли бы воспроизвести проблему с использованием панели Swing, содержащей JTextField и jxbrowser (teamdev.com/jxbrowser).   -  person mabr    schedule 19.04.2012
comment
Проблема возникает только тогда, когда wmode объекта flash не является окном,   -  person javydreamercsw    schedule 25.01.2013


Ответы (4)


Все. Мы только что столкнулись с этой проблемой с другим компонентом браузера (DjProject Native Swing). Все работает нормально в Java 1.6, но в Java-7 мы начали наблюдать странные проблемы, когда вы можете печатать в поле ввода, но если вы выбираете назад, чтобы исправить опечатку, вы не можете печатать после щелчка мыши. Чтобы восстановить, вам нужно было выбрать из поля ввода, а затем вернуться, чтобы продолжить редактирование.

См. http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-Desktop/html/awt.html#gdcqp В частности, часть здесь о синтетическом фокусе и прокси фокуса.

Короче говоря, в нашем случае я смог найти обходной путь, подключив прослушиватель мыши к JWebBrowser.getNativeComponent(). Затем в mousePressed выполните browser.requestFocus(), а затем browser.getNativeComponent().requestFocusInWindow();

Надеюсь, это поможет любому, кто столкнется с этим.

person Adrian    schedule 18.12.2012
comment
Я смог заставить его работать после того, как сделал следующее: скомпилировал с JDK 1.6, запустил с JRE 1.6 и понизил библиотеки swt до 3.8. Последняя часть была единственным изменением, которое заставило его работать. Раньше я использовал 4.x и все еще вижу проблему даже при компиляции/запуске на Java 1.6. - person javydreamercsw; 29.01.2013
comment
Приведенный выше комментарий недействителен, поскольку он не работает при запуске на Java 7 или Java 8, если на то пошло. Смотрите мой ответ ниже. - person javydreamercsw; 30.05.2013
comment
Согласно вашему описанию, это соответствует этой ошибке SWT bugs.eclipse.org/bugs/ show_bug.cgi?id=353683 - person Yves Martin; 13.02.2015

Попробуйте просмотреть FocusListener и WindowFocusListener для реализации слушателей либо для Swing сами компоненты или JFrame. Всякий раз, когда делается вызов focusLost(..), вы можете использовать requestFocus() в окне или компоненте, чтобы принудительно вернуть фокус.

person bgroenks    schedule 19.04.2012
comment
Я не получаю никакой обратной связи с этими параметрами. - person javydreamercsw; 24.01.2013
comment
О каком отзыве вы говорите? - person bgroenks; 25.01.2013
comment
Если я выхожу из вывода, я никогда его не вижу. В нашем случае компонент wmode непрозрачен, поэтому является тяжеловесным компонентом. К сожалению, переход на окно не вариант. - person javydreamercsw; 25.01.2013
comment
Непрозрачность не имеет ничего общего с тяжеловесным компонентом. - person bgroenks; 26.01.2013
comment
Может быть, но, по крайней мере, кажется, что это имеет значение в этом вопросе. - person javydreamercsw; 26.01.2013
comment
Вы используете Frame или JFrame? - person bgroenks; 26.01.2013
comment
JFrame. Есть ли разница? - person javydreamercsw; 27.01.2013
comment
Нет. Но вы можете добавить FocusListener или WindowFocusListener в JFrame. Так что этот метод будет работать просто отлично. - person bgroenks; 27.01.2013
comment
Я пробовал, но не могу зафиксировать события. Печать фиктивных сообщений на консоль ничего не показывает. - person javydreamercsw; 28.01.2013
comment
Я смог заставить его работать после того, как сделал следующее: скомпилировал с JDK 1.6, запустил с JRE 1.6 и понизил библиотеки swt до 3.8. Последняя часть была единственным изменением, которое заставило его работать. Раньше я использовал 4.x и все еще вижу проблему даже при компиляции/запуске на Java 1.6. - person javydreamercsw; 29.01.2013
comment
Ах, вы используете SWT. Это может вызвать проблемы. Так он работает с 3.8? - person bgroenks; 31.01.2013

Наконец-то я нашел рабочий обходной путь. Во время выяснения причины этого было замечено, что щелчок по другому компоненту (например, JLabel) и щелчок назад по текстовому полю работал нормально. Поэтому я воспроизвел это поведение с помощью класса AWT Robot. Дополнительные сведения см. в разделе Репликация поведения мыши в коде.

person javydreamercsw    schedule 30.05.2013

Попробуйте последнюю версию JDK Java 1.7. Это сработало для меня. Раньше я не мог вводить какие-либо данные в текстовые поля. После обновления я не сталкиваюсь с этой проблемой.

http://bugs.sun.com/view_bug.do?bug_id=8018672

person user2368558    schedule 26.12.2013