Bad event on java panel - java

I have a java panel with 4 buttons. When I click on of these buttons, a new frame appears and the first is hidden with setVisibile(false).
On that new window, I have another button, but when i click it, I got the event corresponding to the fourth button of the first window. Clicking the button again does the trick, but of course this is not acceptable.
Am I missing something? I just show the frames with
nameOfTheFrame.setVisible(true);
and I have MouseListeners on every button.
The code of the last button is simply:
System.exit(0);
EDIT
Sample code:
private void btn_joinGamePressed(java.awt.event.MouseEvent evt) {
GraphicsTools.getInstance().getCreateGame().setVisible(false);
GraphicsTools.getInstance().getMainPanel().setVisible(false);
GraphicsTools.getInstance().getRegistration().setVisible(true);
}
GraphicsTools is a Singleton.
EDIT 2
Some more informations.
I noticed that on MAC OS works fine. The problem happens only on Linux and Windows.

This must be happening because of your mouse listeners. May be it is identifying the old button in your first click which is in the same location of new button (It is just my guess).
Change the mouse listeners to action listeners. For a button, it is sufficient if you have action listener.
Try this.

Try calling revalidate() on the frames as you change their viability.
Edit:
It could be something with the creation of the frames. Make sure you are calling 'pack()` on the frames.

Related

ActionListener called twice, added Once

I created one JFrame. This JFrame contains a JLabel, which contains some JButtons. The JButtons have an ActionListener (called MainFrameListener). When the arrowButton Button is clicked a method is executed by the code. This method removes all ActionListeners from the old Buttons with foodButton.removeActionListener(new MainFrameListener());
But although I removed the Listener the Button has still two buttons.
Of course I already searched on the Internet to fix the problem and I found a line of code wich shows the amount of Listeners for one Button.
System.out.println("Count of listeners: " + ((JButton) e.getSource()).getActionListeners().length);
The first time I click on the buttons Java says there are two buttons. When I click on the arrowButton the other menu opens and the buttons are removed. That's all like I want. When I click the arrowBackButton the application sends me back to the MainFrame. That's perfect. But when I click on the arrowButton again the Console says that I have two listeners registered for the Buttons. And the sound which comes on the click is played two times.
I don't understand that because I removed the Listeners. Is there any better method to remove Listeners?
foodButton.removeActionListener(new MainFrameListener()); wont remove anything since you are removing a newly created object that has never been added to foodButton. Keep a reference to your listener and remove it later like this:
MainFrameListener listener = new MainFrameListener();
foodButton.addActionListener(listener);
//and later somewhere else
foodButton.removeActionListener(listener);
But my advice is to avoid adding/removing listeners in the first place.

How to remove GWT menubar on Screen click?

I am a beginner using GWT. I have a menubar which pops-up on a Label click. I need to remove it when the user clicks anywhere on screen except the Label which caused it to display (Legal) I tried various methods like hooking up this event on
RootPanel.get().addDomHandler(clickDetectHandler, ClickEvent.getType());
public void onClick(ClickEvent event) {
Object source = event.getSource();
if (!(source instanceof MenuBar))
panel.remove(menu);
I even tried using the MouseOutEvent but it doesn't detect click. I am able to remove it on a click back to the legal label. But I need it to be removed on detecting a click on the screen. Please advise.
GWT has a panel called PopupPanel which automatically handles exactly the behaviour that you want.
Quoting from the javadoc:
"PopupPanel's constructor takes 'auto-hide' as its boolean parameter.
If this is set, the panel closes itself automatically when the user clicks outside of it."
Is it possible to have the pop-up menu display inside of a PopupPanel?
http://google-web-toolkit.googlecode.com/svn/javadoc/2.5/com/google/gwt/user/client/ui/PopupPanel.html
Have a look at this GWT sample. This seems to have the behaviour you describe. It comes with source code.
Alternatively you can try handling the blur event on the menu widget.

Is removing actionListener necessary when you disable the button?

I'm working on a minesweeper in Java with Swing and I figured it'd be a fast way to get "rid" of a button that was clicked by using
JButton.setEnabled(false); (with a proper icon too, of course).
But do I have to remove all the listeners connected to this button later or is it enough and I can just forget about the said button then?
You have 2 different questions, one in your title, and one in your description.
Is removing actionListener necessary when you disable the button?
As stated in the previous comments, no.
But do I have to remove all the listeners connected to this button later...
Yes, if you have other kinds of listeners. For example, a MouseListener will still fire if the button is disabled. Usually, there is no need for a MouseListener on JButton, but there may be in some corner cases. I'm not sure about the other types of listeners that can be added to a JButton.
Just wanted to clarify.

JButton needs to be clicked twice after JDialog

I've been struggling with some problem while creating my app based on Swing. I have a main JFrame which consists of:
JMenu
JPanel containing a JButton and a JLabel
JButton is linked with ActionListener. Clicking JMenu (MenuListener) brings up a JDialog with some form. The problem is, when the JDialog is closed (it doesn't make difference whether I do it with dispose() or rather showVisible(false)) I need to click the JButton two times before it triggers for the first time. From now it normally works with one click.
Every time the JDialog is in front, the problem appears.
PS. The JDialog is set to be modal, with JFrame as parent.
It sounds like a focus issue.
The first click restores focus to the app and the second clicks the button. Typically, I have seen this when the JDialog has the wrong parent and focus can not be returned.
Thank you for your answers.
I have considered posting some code, but it involves 4 classes so will be quite long.
I have also tried things with focus before, but nothing helped. What is interesting: if I display the JDialog by new myDialog.showVisible(true) it behaves like I've described. But if I use construction like this:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JDialog.setVisible(true);
}
});
it closes normally and parent frame doesn't need to be clicked before responding, but on the other hand the displayed Dialog needs so. Additonally, what I do not understand, after opening the Dialog cursor is placed in the text field and I can write normally, but to click some button on it I must click once on the Dialog, only second and next clicks behave like I want to.
PS. Closing the dialog like in the second included example changes nothing.

How to make a button deep in a nested Swing panel get the "keyboard focus"?

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.

Categories