开发者

Remove the listener for defaultButton in java

i have a Jframe application with the defaultbutton set to btnClose_ (Close Button: this button closes the window). I have 2 textfields that must also fire an event when user clicks the Enter key on the textfields. What happens is that when I press the Enter key while the cursor is on the textfield, the event on the Close button is fired causing the window to close.

Is it po开发者_Go百科ssible to remove the listener of the default button if the Enter key is pressed on the textfield? Here's my code for the textfield listener

/**
 * Receives the two textfield instance
 */
private void addFilterListener(JTextField txf) {
    txf.addKeyListener(new KeyAdapter() {
        /**
         * Invoked when a key has been pressed.
         */
        public void keyPressed(KeyEvent e) {               
            if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                ActionListener al = btnClose_.getActionListeners()[0];
                btnClose_.removeActionListener(al);
                btnFilter_.doClick();
                e.consume();
                btnClose_.addActionListener(al);
            }
        }
    });
}
private JButton getBtnClose(){
if(btnClose == null){
   btnClose.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            getWindow().dispose();
        }

    });
 }
return btnClose;

}

}


Where to start?

The first thing that springs out at me is the bad variable names. txf? What's wrong with proper words? textField or field, say. Or much better, a name descriptive of its purpose, not what it is.

Secondly, the first comment is wrong (not uncommon) and the second comment is redundant (already specified in the KeyListener interface, you don't need to try and half-heartedly specify it again).

Next up, low level key listeners tend not to work so well on Swing components (JComboBox being the most notorious example - it typically is implemented with child components). In general you can use JComponent.registerKeyboardAction (the API docs says this is obsolete but not deprecated, and to use more verbose code). For text components, you often want to play with the document (typically through DocumentFilter). In this particular case, looks like you just want to add an ActionListener.

Now doClick. It's a bit of an evil method. For one thing it blocks the EDT. It is probably the easiest way to make it look as if a button is pressed. From a programming logic point of view, it's best to keep away from modifying Swing components, when you can keep everything in your abstracted code.

Removing and adding listeners from components is generally a bad idea. Your code should determine what to do with an event including whether to ignore it. Do that at an appropriate point when handling the event. Don't duplicate state unnecessarily.

A potential issue is that the code seems to assume that there is precisely one action listener. There could be others. The code is not robust under unexpected behaviour. Set your components up at initialisation time, and you shouldn't need to refer to them again.


As far as I understood your question, you want that buttonClick should not get fired if Enter is pressed .

This won't fire doClick() if enter is pressed

if (e.getKeyCode() != KeyEvent.VK_ENTER) {
                btnFilter_.doClick();
}


In the ActionListener of the close button, assuming you can change its code, don't close if one of the text fields have the focus.

        public void actionPerformed(ActionEvent e) {
            if (field1.hasFocus() || field2.hasFocus())
                return;  // don't close if text field has focus
            frame.dispose();
        }

If you can not change the ActionListener of the close button, add a FocusListener to the text fields. If one of them gets the focus, remove the default button. If the text field lost the focus, reset the default button.

    FocusAdapter listener = new FocusAdapter() {
        @Override
        public void focusGained(FocusEvent e) {
            frame.getRootPane().setDefaultButton(null);
        }
        @Override
        public void focusLost(FocusEvent e) {
            frame.getRootPane().setDefaultButton(close);
        }
    };
    field1.addFocusListener(listener);
    field2.addFocusListener(listener);

This should be better than depending on the listeners being called in the correct sequence - it is of no avail to remove the listener if it was already called...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜