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.
Related
I want to implement key listener on my puzzle game.
i have done it with action listener but now want to move on with key listener.
My logic for action listener was that:
when a specific button is clicked
it checks if is adjacent button's icon is null
if it is null then their icons will be swapped
Now, how can I do it with key listener?
Thank you.
if( b1==e.getSource()){
if(b2.getIcon()==null){
b2.setIcon(b1.getIcon());
b1.setIcon(null);
}
else if(b5.getIcon()==null){
b5.setIcon(b1.getIcon());
b1.setIcon(null);
}
}
You tell us that you have implemented a KeyListener but it's not working. Without code, all we can do is guess, so here's mine:
KeyListeners require focus to work, and so if your GUI has any components that steal the focus, such as JButtons, all JTextComponents such as JTextArea or JTextField, JComboBoxes, JLists,... then your KeyListener won't work.
One kludge is to force the component with the KeyListener to have the focus and to greedily hold on to the focus. This is not advisable since it will force your program to behave abnormally since most users expect buttons to have and retain focus when pressed, and text components won't work if they're not allowed focus.
Again, often the best solution is to use Key Bindings since these can work without requiring focus and are a cleaner way to capture keystrokes. Please look at the Key Bindings Tutorial and then have a look at my example code for using Key Bindings here and here.
Again for better and more specific help, then please tell us more of the details and show us your pertinent code, preferably as a minimal example program or MCVE.
I have two seperate JFrames but when i click the X in the topright of one, it will exit out of the other also. I have an "exit" button near the bottom to do setVisible(false), but i still have the tendency to use the x button. How would i make it so that it doesnt cancel out of the entire project?
Also, how would i make it so that the second JFrame locks out of the other JFrame untill the second JFrame is closed, like how a popup message works
Don't give your GUI two JFrames. The GUI ideally should have only one GUI. If a separate window is required, then make it a dialog such as a JDialog, and this won't happen.
Also, how would i make it so that the second JFrame locks out of the other JFrame untill the second JFrame is closed, like how a popup message works
You are perfectly describing the behavior of a modal JDialog or JOptionPane. Just use 'em.
Later we'll chat about using CardLayouts to swap views in a single GUI.
Edit, you state:
Im using Netbeans form editor to create them faster but I only see JFrame and JPanel. Can I edit them in Netbeans? I'd rather not do them through scratch Java
You've touched on another zealous belief of mine, that this is yet another reason not to use a code generator when learning a library as one can get too tied into the code generator, that it prevents one from learning the library. I strongly advise you to put aside your code-generation tool and create by hand, referring to the tutorials and API. Then later when you get more familiar with the library, sure use the tool. By the way, an answer to your direct question here is to gear your GUI's to create JPanels, and then use these JPanels where and how you want them -- in JFrames, or JDialogs, or JOptionPanes, or swapped in CardLayouts, or JTabbedPanes or nested in other JPanels,... etc...
You should be using a modal JDialog, not a second JFrame, because JDialogs provide certain functionality such as not adding another window bar to the taskbar, and automatically setting focus when the parent JFrame receives focus. Modal JDialogs prevent user input to the JFrame while it's open, useful for an "Are you sure you want to exit?" dialog, for example.
As for one JFrame exiting the other, you probably have their default close operation set to EXIT_ON_CLOSE. If you do this:
jframe.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
jframe.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
handleUserWantsToCloseWindow();
}
});
Then you can control what happens when the user wants to close, such as popping up a "Save Changes?" modal JDialog or "Are you sure you want to quit?" modal JDialog. Note that you have to manually dispose of the JFrame if you use this method.
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
So I have a JDialog with a focus listener that, when the frame is not focused anymore, it hides it. Can I make a key combination that when pressed, to make the frame visible again?
I thought about using the key listener but I suppose the listener works only when the object to whom I added it is focused, so it would be useless in my case.
Well you could take a look at:
http://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
I have a swing frame that contains embedded panels that contain other panels, etc.
Deep down, there is a button. I want the button to get focus so that pressing the "enter" key would generate an actionPerformed event.
However, if I do myButton.requestFocus() or myButton.requestFocusInWindow() the whole window gets the focus, but nothing seems to happen in terms of keyboard.
I'm obviously missing something about the focus subsystem.
Update2: I explicitly added a KeyListener in addition to the ActionListener and now it works. This is really weird, since I thought that actionListener includes both key and mouse actions.
For the enter key to work you probably want to set the default button rather than the keyboard focus:
button.getRootPane().setDefaultButton(button);
If you really want the keyboard focus then your problem might be related to when you call requestFocus. Sometimes if it is called before a component is fully visible it can be ignored. To fix that you can delay the requestFocus call until after other events have been processed:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
button.requestFocus();
}
});
Sounds like requestFocus() is failing at some level. Try testing to see if any of the parent jPanels or other components can request focus, and work your way up to find out where the problem lies.
There is a way to programatically specify the functionality of the tab ( you know when you press tab and the next widget gets selected )
By default it follows the way the components were added.
Using this custom mechanism will let you select your nested button as the first which receive the actionperformed event.
Unfortunately I don't remember what the name for this "mechanism" is, but is something like traversal or focus traversal
First, don't use requestFocus() use requestFocusInWindow(). requestFocus has platform specific issues, while requestFocusInWindow is more consistent.
Your actual problem; the component (or one of its parents) is probably not visible, or has been render non-focusable.
I want the button to get focus so that
pressing the "enter" key would
generate an actionPerformed event.
The is LAF dependents. Enter works in Windows, but not the Metal LAF. Check out Enter Key and Button for more inforation.
The requestFocusInWindow() method only works if the Component is currently visible on the frame. There are no other tricks so we are just making random guesses about what your are doing wrong. If you need further help you need to post a SSCCE demonstrating the problem.
You can get the rootPane of the frame and update the inputMap and actionMap. See the below code.
InputMap map = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
map.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ok");
ActionMap actionMap = getRootPane().getActionMap();
actionMap.put("ok", enterAction);
Here enterAction is a AbstractAction object whose actionPerformed() will be called when user presses Enter.