problem getting rootPane

I've created a very simple app to play around with the FocusTraversalPolicy. The app consists of a JFrame that has 2 JPanels that contain a few text fields. In the JFrame, I added the enter key to the FORWARD_TRAVERSAL_KEYS set in the KeyboardManager. That worked fine and I was able to change the traversal order easily.

Now I want to make the last text field on one of the the Jpanels handle the enter key differently. I want it to fire off a dialog.

The problem I'm having is when I try to get the rootPane. Everything I've tried returns null. Below is the simple JPanel class. In it are 3 different methods I've tried to get the rootPane and all of them return null.

What am I doing wrong? Is there a best practices example that I can follow?

public class P1 extends JPanel {

private JTextField jTextField1 = new JTextField();

private JTextField jTextField2 = new JTextField();

private JTextField jTextField3 = new JTextField();

private JTextField jTextField4 = new JTextField();

public P1() {

init();

}

public void init() {

setBorder( BorderFactory.createEtchedBorder() );

this.add( jTextField1, null );

this.add( jTextField2, null );

this.add( jTextField3, null );

this.add( jTextField4, null );

jTextField1.setText( "Field1" );

jTextField2.setText( "Field2" );

jTextField3.setText( "Field3" );

jTextField4.setText( "Field4" );

MyFocusTraversalPolicy policy = ( MyFocusTraversalPolicy ) KeyboardFocusManager.getCurrentKeyboardFocusManager().getDefaultFocusTraversalPolicy();

policy.addComponent( jTextField1 );

policy.addComponent( jTextField2 );

policy.addComponent( jTextField3 );

policy.addComponent( jTextField4 );

initEventHandlers();

}

private void initEventHandlers() {

// define ids for actions

Object dlg = new Object();

Action dialogAction =

new AbstractAction() {

public void actionPerformed( ActionEvent e ) {

JOptionPane.showMessageDialog( getParent(), "This is a test message." );

}

};

// ********** PROBLEMS START HERE **********

//JComponent rootPane = getRootPane();

//JComponent rootPane = ( JComponent ) SwingUtilities.getRoot( this );

JComponent rootPane = Application1.getFrame().getRootPane();

// Here's where it breaks because rootPane is null

ActionMap am = rootPane.getActionMap();

InputMap im = rootPane.getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );

// add Actions to ActionMap

am.put( dlg, dialogAction );

// add KeyStrokes to InputMap

im.put( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ), dlg );

// add Actions to buttons

jTextField4.addActionListener( dialogAction );

}

}

[2849 byte] By [ferr0084] at [2007-9-27 21:43:31]
# 1
this is easy. you are trying to get the rootPane in your constructor. at that point in time you don't have any, hence you always get null!you only have a root pane, once your panel has been added to some container.thomas
kloeber at 2007-7-7 3:42:10 > top of Java-index,Archived Forums,Swing...
# 2

I was wondering about that. I tried to test your suggestion by making the initEventHandlers method public and calling it explicitly after the object was created and added to the Frame. Like this:

JPanel jPanel1 = new P1();

contentPane.add( jPanel1, null );

jPanel1.initEventHandlers();

This did get rid of the NullPointerException but seems like a clumsy way to solve the problem. Is there a way that this could be done without having the creator call the initEventHandlers method? I can't think of a clever way to have the object initialize it's self after creation and I haven't been able to find an example that demonstrates best practices.

ferr0084 at 2007-7-7 3:42:10 > top of Java-index,Archived Forums,Swing...
# 3

well, i don't know if it's clumsy or not. i reckon it's a matter of taste and preference.

if you don't like it, consider the following:

1) i tend to add listeners only in the class that maintains a component. but if you have to...

2) add a HierarchyListener to your panel. that way you'll know when it is added to the root pane and you can act upon.

3) add a ComponentListener to your panel. that way you know when it is shown/becomes visible. it will have a container at that point in time (however, this might be triggered multiple times during it's life time).

thomas

kloeber at 2007-7-7 3:42:10 > top of Java-index,Archived Forums,Swing...