Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Swing: Focus issue

Tags:

java

focus

swing

I'm making a level editor for my game. I have a property panel where I can modify the selected object its properties. I also have a Save button to write the level xml.

A field-edit is submitted(*) when the editor component lost the focus or Enter is pressed. This is working great, but the only problem is that when I have this sequence of actions:

  1. Edit a field
  2. Press the save button

Because, what happens is this:

  1. I edit the field
  2. I press the save button
  3. The level is saved
  4. The field lost the focus
  5. The edit is submitted

As you can see, this is the wrong order. Of course I want the field to lose its focus, which causes the submit and then save the level.

Is there a trick, hack or workaround to make the field first lose the focus and then perform the action listener of the save button?

Thanks in advance.

(* submit = the edit to the field is also made in the object property)


EDIT: For the field I'm using a FocusAdapter with focusLost:

FocusAdapter focusAdapter = new FocusAdapter()
{

    @Override
    public void focusLost(FocusEvent e)
    {
        compProperties.setProperty(i, getColor());
        record(); // For undo-redo mechanism
    }
};

And for the button a simple ActionListener with actionPerformed`.

btnSave.addActionListener(new java.awt.event.ActionListener() {
     public void actionPerformed(java.awt.event.ActionEvent evt) {
         // Save the level
     }
});
like image 342
Martijn Courteaux Avatar asked Aug 29 '11 09:08

Martijn Courteaux


People also ask

What is focus in Java Swing?

Focus is the mechanism that determines which of the components in a window will receive keyboard input events. A focus manager looks for special keystrokes that change the focus (usually the Tab and Shift-Tab keys), and then decides which component will next get the focus.

Is Swing in Java outdated?

JavaFX new fixes will continue to be supported on Java SE 8 through March 2022 and removed from Java SE 11. Swing and AWT will continue to be supported on Java SE 8 through at least March 2025, and on Java SE 11 (18.9 LTS) through at least September 2026.

What is replacing Java Swing?

Hint: Oracle has developed JavaFX to replace both Swing and AWT. Since Java SE 7, update 6 it is bundled with Java SE. "JavaFX is a set of graphics and media packages that enables developers to (...) deploy rich client applications that operate consistently across diverse platforms" [1].

What is requestFocus in Java?

requestFocus() makes a request that the given Component gets set to a focused state.


1 Answers

Hmm ... can't reproduce: in the snippet below the lost is always notified before the actionPerfomed, independent on whether I click the button or use the mnemonic:

    final JTextField field = new JTextField("some text to change");
    FocusAdapter focus = new FocusAdapter() {

        @Override
        public void focusLost(FocusEvent e) {
            LOG.info("lost: " + field.getText());
        }

    };
    field.addFocusListener(focus);

    Action save = new AbstractAction("save") {

        @Override
        public void actionPerformed(ActionEvent e) {
            LOG.info("save: " + field.getText());
        }
    };
    save.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
    JButton button = new JButton(save);
    JComponent box = Box.createHorizontalBox();
    box.add(field);
    box.add(button);

On the other hand, focus is a tricky property to rely on, the ordering might be system-dependent (mine is win vista). Check how the snippet behave on yours.

  • If you see the same sequence as I do, the problem is somewhere else
  • if you get the save before the lost, try to wrap the the save action into invokeLater (which puts it at the end of the EventQueue, so it's executed after all pending events)

    Action save = new AbstractAction("save") {
    
        @Override
        public void actionPerformed(ActionEvent e) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    LOG.info("save: " + field.getText());
                }
            });
        }
    };
    
like image 81
kleopatra Avatar answered Oct 20 '22 22:10

kleopatra