Focus problems with JDK7 and native components - java

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");
}

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.

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.

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.

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

Related

Java Swing component does not repaint automatically

I am debugging a Java Swing application in which a component (in my case a JButton inside a JPanel inside a JPanel) does not get repainted automatically when it should. For example, when the window is first shown, one can see the JButton there, but when another window overlaps my application's window for a while, the JButton can no longer be seen.
Since I have no idea where to begin, I would like to know what are the most common causes of repainting problems in Swing components.
This would be a good place to start at http://docs.oracle.com/javase/tutorial/uiswing/painting/problems.html
what happens if you minimize both the windows and bring them back on?
you might try calling your jpanel.revalidate() at some point in your code. But I don't know where to call that unless I see your code.

swing focus issue, lost focus, focusgain not invoked

I have a complex and heavy swing client application which contains many modal compponents, jdialogs, internal frames etc. on some cases, a problem occurs and it is impossible to focus on swing textfields anymore. You may click on some jbuttons, jcheckboxes but it is impossible to focus and edit values on editable jtextfields anymore. The gainfocus events of editable textfields are not triggered anymore, only the requestfocus methods are invoked when you perform click on textfields.
I found a way(hack) so resolve the problematic case, when the trouble case occurs, and you show some joptionpane message or modal jdialog and close it by clicking or disposing, the problem goes away any you may click onto the textfields and edit them.
As a solution, i do some check, if you try focusing on a component, i start a timer thread in the requestfocus event of clicked textfield and keep the instance as focusrequesting component. After some time i check the last focused component by
KeyboardManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner()
If no problem occured, and the textfield gained the focus, the returned object (retur value of getPermanentFocusOwner) is the same instance as the focusrequesting component. But if the problematic case occured, the returned object is different from the focus requesting one and i open my temporarily jdialog by:
JDialog dialog=new OptionPane().createDialog(KeyboardFocusManager.getCurrentFocusManager().getActiveWindow(), "");
dialog.setModal(true);
// MUST be modal to fix the lost focus case
// start closing thread, which closes the dialog after some few time by dialog.dispose
new Closer(dialog).start();
dialog.setVisible(true);
This mechanism works, i now it is not very stable. And on some cases,the dialog.dispose() does not work, the temporarily windows remains always on the screen, not closeable, and because it is modal, client can not do any actions anymore. The dialog MUST be modal to solve the focus problem, because non-modal dialogs does not resolve the focus problem declared above. The dispose method of jdialog has many synchronized blocks, mutex objects etc, I think there occurs some deadlocks.
Any better mechanism suggestions, ideas? I know the best solution is to check the current application, analyse it or rewrite it. But it is very complex, heavy and model and view is not well properly organised. I have short time because the client is waiting, need some temporarily solutions, tricks or hacks.
You may click on some jbuttons, jcheckboxes but it is impossible to
focus and edit values on editable jtextfields anymore.
this is issue (quite common) with JTextField in JWindow without parent (JFrame), use undecorated JDialog instead
I saw here some issue with Focus, FocusSubsystem on Linux OS with last Java version, but never caused to block users input to JTextField
the best workaround for a.m. issue is RequestFocusListener by #camickr
dialog.setVisible(true); should be wrapped in invokeLater(), more see in Initial Thread (valid for all Top-Level Containers created on runtime too)
nothing clear from your question without posting an SSCCE, short, runnable, compilable, demonstraded, caused with a.m. issue

AWT Canvas cannot gain focus in the presence of another focusable component

I have a simple GUI with a JTextField and an AWT Canvas (to prevent the counter-question as to why I'm using an AWT Canvas: I need to have a window handle).
The Canvas is to process input events, that means it must be focusable. I assure this by using setFocusable(true) in its constructor, later checks using isFocusable() confirm that it is indeed focusable.
Now, the JTextField gains the focus by default when the GUI opens. That's fine by me so far. However, there is no way to get the focus away from that JTextField.
The article "The AWT Focus Subsystem" clearly states that if a focusable component is being clicked on, it will gain the focus. This does not happen, in fact, I receive zero focus change events whatsoever, only if the window gets deactivated and activated again, but then the focus is right back to the JTextField.
Explicit invocations of requestFocus() and requestFocusInWindow() do not help either, the latter always returns false.
I have gotten the same results with any focusable component if I replace the JTextField. If the Canvas is the only focusable container, everything works fine because it will always have the focus.
Am I missing something here? Is there any way I can make my Canvas gain focus in the presence of another focusable component, preferably without making that one unfocusable?
basically in swing focus gained 1st. left(ToRight) JComponents on the top
in most completed GUI, and if there (together with creating JComponents) are added Listeners to the JComponents, then these Listeners (f.e. Document) can take focus...
but works for me on startUp:
last lines in something class about JComponets ..
myFrame.pack();
myFrame.setVisible(true);
Runnable doRun = new Runnable() {
public void run() {
myComponent.grabFocus();
myComponent.requestFocus();//or requestFocusInWindow
}
};
SwingUtilities.invokeLater(doRun);
Sorry for leaving some info out that turned out to be the root of the problem.
As mentioned, I'm using a heavyweight component so I have a window handle. I need one because it is passed to an OpenGL application in a native library, the AWT canvas is then used as a rendering canvas.
In Windows, Java uses the GWLP_USERDATA window field to store a pointer to an AWTComponent object. However, said OpenGL application overrides that field to store its own Window object pointer, which will of course break all AWT related functionality.
I solved this problem by creating a custom window message handler that delegates incoming messages to both the OpenGL application and Java's AWT part.

focus for java applets

I made a java game that is all based on JPanel. When I add it to a JFrame it works perfectly, and when I add it to a JApplet and test it with the built in applet tester of eclipse it works perfectly. However, when I try to run the applet through an html site it doesn't work. It loads, but it doesn't take keyboard input. I have it set up where "pressing s" starts the game, but even when I click on the game and press s, nothing happens.
Do I have to set the keyboard focus, because I thought that was done automatically.
but it doesn't take keyboard input.
KeyEvents are only passed to the component that has focus. I would guess your panel doesn't have focus, so make sure you make the panel focusable and then use the requestFocusInWindow() method once the GUI is visible to make sure the panel has focus.
However, the better solution to the problem is not to rely on the KeyListener but instead to use Key Bindings. Swing was designed to use Key Bindings.
Read more about Key Bindings.

Lightweight Component over Heavyweight Component problem

The code pretty huge and involves a lot of different class/methods:
But here is the gist:
There is a main frame : A_Main
Selecting something in the main frame A: opens a JDialog B_Dialog
This B_Dialog has a JPanel on it: C_Panel
This C_Panel comprises of a textfield and a button
On clicking on the textfield/button: opens a tooltip and another JPanel: D_Panel
Now, the problem is:
1) The tooltip overflows the size of B_Dialog and therefore gets truncated
2) D_Panel however; even if its outside the boundary of B_Dialog gets displayed fully
2.1) There are some texfields and drop down menus in this D_Panel
2.2) The mouse events function correctly in this D_Panel items (drop down menus)
2.3) But Keyboard events do not function correct (Textfield)
I would be glad if you could help!
Thanks!
This can only be done in newer versions of the JDK.
See, Mixing Heavyweight and Lightweight Components.
Now, when I try to enter something in the JAR JPanel's text field, I am not able to do so as this pops out of the border of the main JDialog that contains it.
Add a JScrollPane around the JPanel, and allow it to expand both horizontally and vertically. If this doesn't work, you may need a customized Layout Manager, or use one of the default ones like GridBagLayout.
Also, you'll need to gain focus before you can enter text, but that doesn't seem to be the problem here.

Categories