简体   繁体   中英

Reconstruct JFrame after using dispose by static method in nested static class

I have a public class AppHelper for displaying some help content using a jframe. There is an exit button on the same JFrame which on click disposes the jframe. The ActionListener is implemented as a static nested class of the class mentioned above.

Also all the components of the help window are defined in the outer class and all of them are private and static. Also the method that shows the help window is static.

Here is some code that I have implemented:

public class AppHelper {
// helper frame
private static JFrame appHelperFrame;
// helper panel
private static JPanel appHelperPanel;
// helper pane
private static JEditorPane appHelperPane;
// exit helper button
private static JButton exitAppHelperButton;
// constraints
private static GridBagConstraints appHelperPaneCons, exitAppHelperButtonCons;

/**
  set layout
 */
private static void setLayoutConstraints () {
    // defines layout
}
/**
 * initialize the helper elements
 * @param void
 * @return void
*/
public static void initializeElements () {
    // initialize constraints
    setLayoutConstraints();
    // handler
    AppHelper.AppHelperHandler appHelpHandler = new AppHelper.AppHelperHandler();

    appHelperFrame = new JFrame("App Help");
    appHelperPanel = new JPanel();
    appHelperPanel.setLayout(new GridBagLayout());

    appHelperPane = new JEditorPane();
    exitAppHelperButton = new JButton("Exit");

    exitAppHelperButton.addActionListener(appHelpHandler);
    java.net.URL helpURL = null;
    try {
        helpURL = new File("AppHelp.html").toURI().toURL();
    } catch (MalformedURLException ex) {
        Logger.getLogger(AppHelper.class.getName()).log(Level.SEVERE, null, ex);
    }
    try {
        appHelperPane.setPage(helpURL);
    } catch (IOException ex) {
        Logger.getLogger(AppHelper.class.getName()).log(Level.SEVERE, null, ex);
    }
    appHelperPane.setEditable(false);
    appHelperFrame.add(appHelperPanel);
    appHelperPanel.add(appHelperPane, appHelperPaneCons);
    appHelperPanel.add(exitAppHelperButton, exitAppHelperButtonCons);
    appHelperFrame.setSize(350, 400);
    appHelperFrame.setResizable(false);
    appHelperFrame.setVisible(true);
}

/**
 * TODO
 */
public static void showAboutApp() {
    //throw new UnsupportedOperationException("Not yet implemented");

}

/**
 *
 * Acts as the handler for the help window components
 * Implement actionListener interface.
 */
private static class AppHelperHandler implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if(source == exitAppHelperButton)  {
            appHelperFrame.dispose();
        }
    }
}
}

The reason of disposing the JFrame instead of setting it invisible is that I dont want this JFrame to consume memory when this JFrame is not in use.

Now the problem is first time I click on the help button (on some other window) the JFrame is shown. Now when I click the exit button on this help window the JFrame is disposed by the handler. Next time I again click on the help button, the help window is not shown. I wanted to know if there is any error in my code or I need to do some thing else.

The javadoc of Window.dispose() states that

The Window and its subcomponents can be made displayable again by rebuilding the native resources with a subsequent call to pack or show.

And that works too, I've tried it. Just call appHelperFrame.setVisible(true) and that's all. If the window is not activated, try calling appHelperFrame.setState(Frame.NORMAL) which will acitvate it.

You only have to call your initializeElements method once though. Your showAboutApp() method should look something like this:

public static void showAboutApp() {
    if (appHelperFrame == null)
        initializeElements(); // This also makes the frame visible
    else {
        appHelperFrame.setVisible(true);
        appHelperFrame.setState(Frame.NORMAL);
    }
}

Final note:

If you always call this showAboutApp() from the EDT (Event Dispatching Thread) then you're good. If you call this from multiple threads, you might want to execute it in the EDT with like SwingUtilities.invokeAndwait() or SwingUtilities.invokeLater() which also ensures synchronization between multiple threads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM