requestFocus() in a JMEDesktop doesn't work

Since the default tab key's focus-changing behavior doesn't work in the JMEDesktop, I figured I'd implement my own. But when I did, I found that calling requestFocus() on any component (including a JInternalFrame) doesn't do anything, and does not request the focus. This may be the root of the default behavior problem, too.



See my test case below. When you run it you will see two JTextFields. Click in the first one, then press tab. You will see the message printed to the console, but field2 does not focus, though it should according to my code in the keyPressed.



Here's the code:

import java.awt.event.*;

import javax.swing.*;

import com.jme.app.SimpleGame;
import com.jme.image.Texture;
import com.jme.input.*;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.*;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jmex.awt.swingui.JMEDesktop;

public class RequestFocusTest extends SimpleGame implements KeyListener {

    public static void main( String[] args ) {
        new RequestFocusTest();
    }

    public RequestFocusTest() {
        this.setConfigShowMode( ConfigShowMode.AlwaysShow );
        this.start();
    }
   
    JTextField field1, field2;
   
    @Override
    protected void simpleInitGame() {
       JMEDesktop jmedesktop = new JMEDesktop("jmedesktop1");
       jmedesktop.setup(display.getWidth(), display.getHeight(), false, input);
       
       /* register the mouse */
      Mouse mouse = new AbsoluteMouse("Mouse Input", display.getWidth(),
                display.getHeight());
        mouse.registerWithInputHandler( input );
        mouse.setLocalScale(new Vector3f(1, 1, 1));
       
        /* invalid texture; the "missing texture" image will show */
      Texture texture =
           TextureManager.loadTexture(
                  RequestFocusTest.class.getClassLoader().getResource(
                  "anytexture.png"),
                  Texture.MinificationFilter.Trilinear,
                  Texture.MagnificationFilter.Bilinear);
      
      TextureState ts = display.getRenderer().createTextureState();
      ts.setEnabled(true);
      ts.setTexture(texture);
      mouse.setRenderState(ts);
      
      Node cursor = new Node("Cursor");
      cursor.attachChild( mouse );
      rootNode.attachChild(cursor);
       
      /* now set up the test JDesktopPane */
       JDesktopPane pane = jmedesktop.getJDesktop();
       
       JInternalFrame frame1 = new JInternalFrame("Test Frame");
       frame1.setSize(300,300);
       JPanel panel = new JPanel();
       
       panel.add(new JLabel("Field1:"));
       
       field1 = new JTextField(10);
       /* disable focus traversal keys, to allow "tab" presses to be handled
        * by our own KeyListener
        */
       field1.setFocusTraversalKeysEnabled(false);
       field1.addKeyListener(this);
       panel.add(field1);
       
       panel.add(new JLabel("Field2:"));
       
       field2 = new JTextField(10);
       panel.add(field2);
       frame1.add(panel);
       
       frame1.pack();
       pane.add(frame1);
       
      frame1.setVisible(true);
       
      Node desktopNode = new Node("desktopNode");
      desktopNode.attachChild(jmedesktop);
      
      rootNode.attachChild(desktopNode);
      
      /* extra stuff to keep the JMEDesktop on-screen properly */
        desktopNode.getLocalRotation().set( 0, 0, 0, 1 );
        desktopNode.getLocalTranslation().set( display.getWidth() / 2, display.getHeight() / 2, 0 );
        desktopNode.getLocalScale().set( 1, 1, 1 );
        desktopNode.setRenderQueueMode( Renderer.QUEUE_ORTHO );
        desktopNode.setCullHint( Spatial.CullHint.Never );
       
        rootNode.setLightCombineMode(Spatial.LightCombineMode.Off);
        rootNode.setCullHint( Spatial.CullHint.Never );
        rootNode.updateRenderState();
        rootNode.updateGeometricState(0, true);
    }

    @Override
    protected void simpleUpdate() {}

   @Override
   public void keyPressed(KeyEvent arg0) {
      if(arg0.getKeyCode() == KeyEvent.VK_TAB) {
         System.out.println("tab pressed; requesting focus");
         field2.requestFocus();
      }
   }

   @Override
   public void keyReleased(KeyEvent arg0) {}

   @Override
   public void keyTyped(KeyEvent arg0) {}
}



Help!!!

-Ricket

EDIT:
Also ntoe I left off SwingUtilities methods, the "proper" way (calling Swing methods in the AWT thread), to keep the test case more simple. They should not make a difference. Furthermore, the important part of this test case, the line "field2.requestFocus()", is already inside the AWT thread because it is part of KeyListener.

I FINALLY found the solution!!! (I've been bummed about this for a couple weeks)



I really don't know why requestFocus doesn't work, it seems to be totally ignored. I debugged JMEDesktop.setFocusOwner and it wasn't called when requestFocus was called; and it's the method that handles focus.



So instead, in my test case I made the JMEDesktop variable "jmedesktop" a member of the whole class, and then in the keyPressed event, I simply call jmedesktop.setFocusOwner(field2); and it WORKS!!!



Of course, there is still the problem that requestFocus() doesn't work when it should. But at least this is a suitable workaround until it's fixed.

THANK YOU!



That helped me a lot. I was trying to make swing focus my "login" form and NOTHING I've tried before worked.



I hope this get somehow implemented or fixed in JME3.



Hugs

To set your expectations, JMEDesktop, as delivered, has many focus and input problems.  Some apps (especially small-scale apps) can just avoid these problems.