Java Swing: Focus Problem

I am creating a level editor for my game. I have a properties panel where I can change selected objects with my properties. I also have a Save button to write the xml level.

When editing a text field (*) when the editor button is pressed, focus or Enter is lost . This works fine, but the only problem is that when I have this sequence of actions:

  • Change field
  • Click save button

Because what happens is:

  • I edit the field
  • I click save
  • Level saved
  • The field has lost focus
  • Editing is sent

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

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

Thanks in advance.

(* submit = field editing is also performed in the property of the object)


EDIT : for the field, I am using 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 } }); 
+7
source share
2 answers

Hmm ... can’t reproduce: in the fragment below the lost it is always reported before the action Performance, regardless of whether I press the button or use the mnemonics:

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

Focus, on the other hand, is a complex property that you can rely on; ordering can be system dependent (mine is a winning prospect). Check how this snippet behaves on yours.

  • If you see the same sequence as me, the problem is elsewhere
  • if you get the save before losing, try wrapping the save action in invokeLater (which puts it at the end of the EventQueue, so it runs after all the 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()); } }); } }; 
+3
source

Normally, wrapping your save code in SwingUtilities.invokeLater() should do the trick. As you mentioned, this does not work? Try the following:

 private boolean editFocus = false; FocusAdapter focusAdapter = new FocusAdapter() { @Override public void focusGained(FocusEvent e){ editFocus = true; } @Override public void focusLost(FocusEvent e){ compProperties.setProperty(i, getColor()); record(); // For undo-redo mechanism editFocus = false; if (saveRequested){ save(); } } }; 

and for your button:

 private boolean saveRequested = false; btnSave.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { if (editFocus){ saveRequested = true; return; } else { save(); } } }); 

and then your save method:

 private void save(){ // do your saving work saveRequested = false; } 

This only works when your focusLost is called after the action of your button. If suddenly the order is correct, this code will receive a save () call twice.

But then again, wrapping your save () code in your original approach should work, because the save code will be executed after all events have been processed. That is, after processing the button click and focusLost events. Since your focusLost code is executed immediately (it is not completed in invokeLater ()), the focusLost code should always be executed before your save code. This does not mean that the order of events will be correct! But the code associated with the events will be executed in the correct order.

0
source

All Articles