0

Hallo,

ich habe einen JDialog, bei dem einer der buttons der Default Button ist. Funktioniert. Wenn ich aber den Dialog mit

dlg. dispose() 

schließe und die selbe Dialog-Instanz später mit

dlg.pack()  
dlg.setVisible(true)  

wieder öffne, ist der Button nicht mehr Default. Als "Arbeiteherum" kann man den Button nach dem Aufruf von pack() erneut als Default setzen. Ich wüsste trotzdem gern, ob es einen guten Grund für dieses Verhalten gibt oder ob ich irgendwas falsch mache.

Danke, Norbert

flag

2 Answers

0

Das Abräumen des Dialogs mit dispose() führt (über den Container) ein removeNotify() auf allen Komponenten aus; also auch dem JButton. Dort wird der Button von der RootPane des Dialogs als Default entfernt. JButton-Javadoc:

to ensure the RootPane doesn't hold onto an invalid button reference

Wir können dies fixen in dem wir eine neue Unterklasse von JButton schreiben und so benutzen:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;

public class DefaultButtonAfterDisposedDialogExample implements ActionListener
{

  public DefaultButtonAfterDisposedDialogExample()
  {
    DefaultForeverJButton b = new DefaultForeverJButton( "Tweaked Button" );

    b.addActionListener( this );
    JDialog d = new JDialog();
    d.add( b );
    d.getRootPane().setDefaultButton( b );
    d.pack();
    d.setVisible( true );

    d.dispose();
    d.pack();
    d.setVisible( true );

    //    b.requestFocusInWindow();//fix to get the focus back (to be able to perform the Action using the spacebar)
  }

  public void actionPerformed( ActionEvent e )
  {
    System.out.println( "actioning !" );
  }

  public static void main( String[] args )
  {
    DefaultButtonAfterDisposedDialogExample g = new DefaultButtonAfterDisposedDialogExample();
  }



  public class DefaultForeverJButton extends JButton
  {
    public DefaultForeverJButton( String string )
    {
      super( string );
    }

    /**
     * We don't like the removing of the DefaultButton in JButton.removeNotify() but want to preserve the
     * actions from AbstractButton.removeNotify() up to Component.removeNotify().<br/>
     * There is no "super.super.method()" in Java, so we have to revert the unwanted code of
     * JButton.removeNotify().
     */
    @Override
    public void removeNotify()
    {
      JRootPane root = SwingUtilities.getRootPane( this );
      boolean iWillHaveToReAddMeLaterAsDefaultButton = false;

      if ( root != null && root.getDefaultButton() == this )
        iWillHaveToReAddMeLaterAsDefaultButton = true;

      super.removeNotify();

      if ( iWillHaveToReAddMeLaterAsDefaultButton && root != null )
        root.setDefaultButton( this );
    }
  }

}

Ob dies schön ist und ob dadurch Probleme mit "invalid button references" entstehen können, mögen andere beurteilen ;-)

link|flag
0

Laut Doku http://java.sun.com/javase/6/docs/api/java/awt/Window.html#dispose() sollte genau das eigentlich NICHT passieren:

The Window and its subcomponents can be made displayable again by rebuilding the native resources with a subsequent call to pack or show. The states of the recreated Window and its subcomponents will be identical to the states of these objects at the point where the Window was disposed

Hast du evtl. mal ein kurzes Beispiel? Welche Java-Version genau nutzt du?

link|flag
Ich hab das jetzt auch mal ausprobiert: Das scheint tatsächlich eine Unklarheit in der Doku zu sein. Als alternativer Workaround wäre ein setVisible(false) anstelle des dispose() möglich. – dadadom Apr 30 at 5:36
Ich nutze lieber dispose(), weil nicht immer klar ist, ob das Fenster nochmal benutzt wird. Es scheint, als ob die Default-Button-Eigenschaft nicht direkt bei den Komponenten gespeichert ist (wo es auch nach dispose bleibt), sondern irgendwo anders. – norbertkulawik May 3 at 8:58

Your Answer

Get an OpenID
or

Not the answer you're looking for? Browse other questions tagged or ask your own question.