Focus problems with JDK7 and native components

2019-02-09 20:57发布

问题:

We have a swing application which embeds a IE ocx component via JNIWrapper.

After switching from jdk6 to jdk7 we start noticing focus problems. When the embedded IE shows a web page with text fields (e.g. the google search page) than the trouble starts:

The Browser 'catches' the focus, so u can start typing in the search text field. Every key typed goes to the IE ocx. But swing seems to ignore this focus change. Even if i change the focus to a swing text field (and swing shows the blinking input cursor), all typed keys goes to the IE ocx

The only way to 'fix' the focus is to deacitvate and activate the main frame. after that the focus seems to be consistent. But if i click in the google search text field again, the focus is broken again.

It seems there is a big change to focus handling in jdk7. From the link:

On the Windows platform, a concept of “synthetic focus” has been implemented. It means that a focus owner component only emulates its focusable state whereas real native focus is set to a “focus proxy” component. This component receives key and input method native messages and dispatches them to a focus owner. Prior to JDK7 a focus proxy component was a dedicated hidden child component inside a frame/dialog. In JDK7 a frame/dialog itself serves as a focus proxy. Now it proxies focus not only for components in an owned window but for all child components as well. A simple window never receives native focus and relies on focus proxy of its owner. This mechanism is transparent for a user but should be taken into account when debugging.

Anyone has an idea to 'fix' the behavior?

EDIT: Here some code to reproduce the problem with 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");
}

回答1:

All - We just experienced this problem with another browser component (DjProject Native Swing). Everything works fine under Java 1.6 but under Java-7 we started seeing weird problems where you can type into an input box but if you select backwards to fix a typo you could not type after making the mouse click. To recover you had to select out of the input field and then back in to continue your edit.

See http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-Desktop/html/awt.html#gdcqp Particularly the part here about sythentic focus and focus proxies.

Anyway to cut a long story short - in our case I was able to find a work-around by attaching a mouse listener to the JWebBrowser.getNativeComponent(). Then on mousePressed execute a browser.requestFocus() followed by a browser.getNativeComponent().requestFocusInWindow();

Hope this helps anyone else that comes across this.



回答2:

Try looking at FocusListener and WindowFocusListener to implement the listeners for either the Swing components themselves or the JFrame. Whenever a call is made to focusLost(..) it you can use requestFocus() on the Window or Component to force the focus to return.



回答3:

I finally found a working workaround. During figuring out what was causing this it was noticed that clicking on another component (i.e. a JLabel) and clicking back on the text field worked fine. So I replicated that behavior using AWT Robot class. See more details in Replicating Mouse behavior in Code.



回答4:

Try the latest jdk of Java 1.7. It worked for me. Earlier, I was not able to enter any input in the text fields. After upgrading, I do not face that problem.

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