There seems to be a problem with focus traversal in the jdk. If you enable
KEY_EVENT_MASK in a component, shift tab ceases to function properly. 

Window.handleTabEvent(KeyEvent e) only changes focus on KEY_PRESSED which
it never gets if you enable KEY_EVENTS!

"tab"       generates 
  KEY_PRESSED(tab)   
  KEY_TYPED(tab)
  KEY_RELEASED(tab)

"shift-tab" generates 
  KEY_PRESSED( shift ) 
-- KEY_PRESSED( tab ) and KEY_TYPED( tab ) events are NOT thrown!
  KEY_RELEASED( tab )
  KEY_RELEASED( shift )

This also happens in jdk1.1.7 on solaris, so I guess there's nothing we
can do about it, but here's an example anyway. It also contains an
optional workaround.

import java.awt.*;
import java.awt.event.*;

public class test
{
  public static void main( String[] argv )
  {
    Frame f = new Frame();
    f.setLayout( new FlowLayout() );
    f.add( new Foo( true, false ) );
    f.add( new Foo( true, false ) );
    f.add( new Foo( true, false ) );
    f.pack();
    f.show();
  }
}

class Foo extends Component
{
  boolean hasFocus   = false;
  boolean workaround = false;

  public Foo( boolean breakFocus, boolean workaround )
  {
    enableEvents( AWTEvent.MOUSE_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK );

    if ( breakFocus )
    {
      enableEvents( AWTEvent.KEY_EVENT_MASK );
    }

    this.workaround = workaround;
  }

  public Dimension getPreferredSize()
  {
    return( new Dimension( 50, 50 ) );
  }

  public void paint( Graphics g )
  {
    g.setColor( hasFocus ? Color.red : Color.black );
    g.fillRect( 0, 0, getSize().width, getSize().height );
  }

  public void processEvent( AWTEvent e )
  {
    switch( e.getID() )
    {
      case KeyEvent.KEY_RELEASED:
          KeyEvent ke = ( KeyEvent ) e;
          if ( workaround && 
               ke.isShiftDown() && 
               ke.getKeyCode() == ke.VK_TAB )
          {
            dispatchEvent( new KeyEvent( this,
                                         ke.KEY_PRESSED,
                                         ke.getWhen(),
                                         ke.getModifiers(),
                                         ke.getKeyCode(),
                                         ke.getKeyChar() ) );
          }
          break;

      case MouseEvent.MOUSE_PRESSED:
          requestFocus();
          break;

      case FocusEvent.FOCUS_GAINED:
          hasFocus = true;
          repaint();
          break;

      case FocusEvent.FOCUS_LOST:
          hasFocus = false;
          repaint();
          break;
    }

    super.processEvent( e );
  }

  public boolean isFocusTraversable()
  {
    return( true );
  }
}
--
Karl LaRocca <[EMAIL PROTECTED]>

Reply via email to