1

My class Output.java extends JPanel. From another class, the user can click on an icon and then it locally creates a JFrame with the Output.java. We found that sometimes the user minimizes that window and then will want it back. He will then reclick on the icon and the JFrame is recreated. By doing it a few times, the Output.java class is displayed several times.

I've found that it is possible to disable multiple JFrame creation by adding this:

    if (!output.isShowing())
        openPage(output);

But it doesn't restore the JFrame. Is there a way to restore a minimized JFrame in this situation?

icon.addMouseListener(new MouseAdapter() {  
    public void mouseClicked(MouseEvent e) {  
        openPage(outputsSlavePane);
    }  
});

private void openPage(final Output panel) {
    JFrame frame = new JFrame("Output");
    frame.add(panel);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            panel.setLostFocus();
        }
    });
}

Thanks.

trincot
  • 317,000
  • 35
  • 244
  • 286
Synor
  • 333
  • 1
  • 4
  • 13

2 Answers2

3

You can restore a minimized frame by calling

frame.setState(JFrame.NORMAL);

The current state of the frame can be retrieved by

frame.getState() // NORMAL or ICONIFIED
wero
  • 32,544
  • 3
  • 59
  • 84
3
  1. Don't keep creating new JFrames.
  2. Instead create a field that references the JFrame, and restore the field, not a new JFrame.
  3. Create a field to reference the JDialog. If the field is null, then locally create it and assign it to the field (this is called "lazy" creation). If the field isn't null, don't re-create it, just display it.
  4. Having said this, most all Swing GUI applications should have only one JFrame, only one main application window. If sub-windows are needed, they should be JDialogs, not JFrames. Please check out The Use of Multiple JFrames, Good/Bad Practice?

An example of "lazy" creation:

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class LazyCreation extends JPanel {
    private static final int PREF_W = 400;
    private static final int PREF_H = PREF_W;
    private Output output = new Output();
    private JDialog outputDialog = null;

    public LazyCreation() {
        add(new JButton(new DisplayOutputAction("Display Output")));
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private class DisplayOutputAction extends AbstractAction {
        public DisplayOutputAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            // lazily create dialog here
            if (outputDialog == null) {
                Window currentWin = SwingUtilities.getWindowAncestor(LazyCreation.this);
                outputDialog = new JDialog(currentWin, "Output Dialog", ModalityType.MODELESS);
                outputDialog.add(output);
                outputDialog.pack();
                outputDialog.setLocationRelativeTo(currentWin);
            }
            outputDialog.setVisible(true);

        }
    }

    private static void createAndShowGui() {
        LazyCreation mainPanel = new LazyCreation();

        JFrame frame = new JFrame("LazyCreation");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}


class Output extends JPanel {
    private JLabel label = new JLabel("Output", SwingConstants.CENTER);

    public Output() {
        label.setFont(label.getFont().deriveFont(Font.BOLD, 36));
        add(label);
    }
}
Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thanks, I'll check it out. But I wonder, if I use the same pattern, wouldn't I get the same situation? If I only replace the JFrame with JDialogs, how would it be possible to restore it when minimized? I still don't have any reference since it has been locally created. I am open to change the patterns, but it has been made this way because multiple windows can be opened simultaneously. – Synor Nov 27 '15 at 15:23
  • @Nicolas: Again, create a field to reference the JDialog. If the field is `null`, then locally create it and assign it to the field (this is called "lazy" creation). If the field isn't null, don't re-create it, just display it. – Hovercraft Full Of Eels Nov 27 '15 at 15:26
  • I wanted to avoid using global variables, but it seems impossible as I can understand. Thanks! – Synor Nov 27 '15 at 15:30
  • @Nicolas: this isn't "global" it's a private instance field, that's it, and this is an appropriate reason for using this, since you need a reference to the dialog outside of its method of creation. – Hovercraft Full Of Eels Nov 27 '15 at 15:31
  • @Nicolas: edit: you can't even minimize a JDialog, so if that messes you up, then consider going with a JFrame. – Hovercraft Full Of Eels Nov 27 '15 at 15:37
  • @Nicolas: see example of lazy creation above. – Hovercraft Full Of Eels Nov 27 '15 at 15:38
  • 1
    Thanks, I better understand now. I will give a try to JDialog, and if the customers wants minimizable windows, I'll suggest to check for JInternalFrame. – Synor Nov 27 '15 at 15:51