Search code examples
javaswingjframedispose

Java Frames disposal creates extra empty frame


I am making a simple login application, but every time i press a button to open another frame(From another class) i get an extra empty frame for some reason. I tried testing it by writing a new class and connecting it to another button.. that class just had JFrame.. and it would still give me another empty frame.

Code

package application;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
/**
 *
 * @author 
 */
public class MainScreen extends JFrame{
    private JFrame frame;// frame of the interface
    private JPanel panel = new JPanel();
    private JPanel left = new JPanel();
    private JPanel center = new JPanel();
    private JPanel top = new JPanel();
    private JButton approve = new JButton("Approve");
    private JButton review = new JButton("Review");
    private JButton employmentCreate = new JButton("Create/Modify");
    private JLabel PR = new JLabel("Personal Records");
    private JLabel ER = new JLabel("Employment Records");
    private JLabel PerR = new JLabel("Perform Review");
    private JLabel AR = new JLabel("Approve Records");
    private JLabel news = new JLabel("There are no news");
    private JLabel empty = new JLabel();
    private JButton logout = new JButton("Logout");
    private JButton personalCreate = new JButton("Create/Modify");
    private JLabel welcome = new JLabel("Welcome:");
    private JLabel userLbl = new JLabel("USERNAME GOES HERE");

    public MainScreen()
    {
        makeFrame();
    }
    private void makeFrame()
    {
       frame = new JFrame("Main Screen");  
       frame.setSize(650,550);
       frame.setResizable(false);
       makeMenuBar(frame);
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       Container contentPane = frame.getContentPane();
       //makes application start in the center of the screen
       Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
       frame.setLocation(d.width/2 - frame.getWidth()/2, d.height/2 - frame.getHeight()/2);
       //border
       UIManager.getDefaults().put("TitledBorder.titleColor", Color.BLACK);
       Border lowerEtched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
       TitledBorder title = BorderFactory.createTitledBorder(lowerEtched, "Main Screen");
       Font titleFont = UIManager.getFont("TitledBorder.font");
       title.setTitleFont( titleFont.deriveFont(Font.ITALIC + Font.BOLD) );
       panel.setBorder( title );
       //border end
       frame.setVisible(true);  
       frame.add(panel);
       panel.setLayout(new BorderLayout());
       panel.add(top, BorderLayout.PAGE_START);
       top.add(welcome);
       top.add(userLbl);
       panel.add(left, BorderLayout.LINE_START);
       left.add(news);
       panel.add(center, BorderLayout.CENTER);
       left.setPreferredSize(new Dimension(200,150));
       center.setLayout( new GridLayout(5,2));
       center.add(PR);
       center.add(personalCreate);
       personalCreate.addActionListener(new ActionListener()
        {public void actionPerformed(ActionEvent e) 
        {
            frame.dispose();
            PR pr = new PR();
            pr.setVisible(true);
        }
         });
       center.add(ER);
       center.add(employmentCreate);
       employmentCreate.addActionListener(new ActionListener()
        {public void actionPerformed(ActionEvent e) 
        {
            frame.dispose();
            ER er = new ER();
            er.setVisible(true);
        }
         });
       center.add(PerR);
       center.add(review);
       center.add(AR);      
       center.add(approve);
       center.add(empty);
       center.add(logout);

       //border
       UIManager.getDefaults().put("TitledBorder.titleColor", Color.BLACK);
       TitledBorder title2 = BorderFactory.createTitledBorder(lowerEtched, "News");
       Font title2Font = UIManager.getFont("TitledBorder.font");
       title.setTitleFont( titleFont.deriveFont(Font.ITALIC + Font.BOLD) );
       left.setBorder( title2 );
       //border end



    }
     /**
     * Receive notification of an action.
     */
    public void actionPerformed(ActionEvent event) 
    { 
        System.out.println("Menu item: " + event.getActionCommand());
    } 

    /**
     * Quits the application.
     */
    private void quit()
    {
        System.exit(0);
    }
       /**
     * About pop up.
     */
    private void about()
    {
        JOptionPane.showMessageDialog(frame, 
                    "Group Project Application",
                    "About Application",
                    JOptionPane.INFORMATION_MESSAGE);
    }
    /**
     * Restarts the application
     */
    private void restart()
    {
       frame.dispose();
        makeFrame();
    }
      /**
     * Creates the main frame's menu bar with menu items.
     */
    private void makeMenuBar(JFrame frame)
    {
        JMenuBar menubar = new JMenuBar();
        frame.setJMenuBar(menubar);
        JMenu menu;
        JMenuItem item;

        // create's File menu
        menu = new JMenu("File");
        menubar.add(menu);
        //restart application
        item = new JMenuItem("Restart");
        item.addActionListener(new ActionListener()
        {public void actionPerformed(ActionEvent e) { restart(); }
         });
        menu.add(item);
        //quit button
        item = new JMenuItem("Quit");
        item.addActionListener(new ActionListener()
        {public void actionPerformed(ActionEvent e) { quit(); }
         });
        menu.add(item);       

        //create's About menu
        menu= new JMenu ("Help");
        menubar.add(menu);

        item = new JMenuItem("About");
        item.addActionListener(new ActionListener() 
        { public void actionPerformed(ActionEvent e) { about(); }
        });
        menu.add(item);

    }

}

Solution

  • MainScreen extends JFrame unnecessarily. And so when you create a MainStream object, you create and display two JFrames, one that is the MainStream object and one that is created by the MainStream object. But more importantly, your classes are too complex and not self contained making it difficult to test them in isolation. Consider re-coding this using SOLID design principles. This will make your code much easier to debug and to enhance.


    Change

      login.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
    
            // .... etc...
    
            JOptionPane.showMessageDialog(null, "Welcome");
            frame.dispose();
    
            MainScreen s = new MainScreen();
            s.setVisible(true);
         }
    

    to

      login.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
    
            // .... etc...
    
            JOptionPane.showMessageDialog(null, "Welcome");
            frame.dispose();
    
            MainScreen s = new MainScreen();
            // !!  s.setVisible(true);  // don't call this!
         }
    

    And don't have MainScreen extend JFrame.

    There are a lot of other problems with your code, but this is the cause of your current bug.

    Other issues:

    • Ignoring exceptions. Read the exception tutorial so you won't be flying blind.
    • Mixing database code with GUI code. Try to keep them in separate testable units.
    • Extending JFrame unnecessarily. You almost never need or want to do this.
    • Swapping JFrames where you should be showing a single stable JFrame for the most part and swap JPanel views.
    • callling setVisible(true) on your JFrames before adding all components to them. This can cause creation of empty JFrames. Always call setVisible(true) after adding components.

    Simplified test program to show that my suggestions work:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Application {
       public static void main(String[] args) {
          new Login();
       }
    }
    
    class Login {
       private JFrame frame;// frame of the interface
       private JButton login = new JButton("Login");
       private JPanel panel = new JPanel();
    
       public Login() {
          makeFrame();
       }
    
       private void makeFrame() {
          frame = new JFrame("Login");
          frame.setSize(300, 200);
          // !! frame.setVisible(true);
          frame.add(panel);
          panel.add(login);
          login.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "Welcome");
                frame.dispose();
                MainScreen s = new MainScreen();
                // s.setVisible(true); // !! get rid of
             }
          });
          frame.setVisible(true);
       }
    }
    
    class MainScreen {
       private JFrame frame;// frame of the interface
       private JPanel panel = new JPanel();
       private JPanel left = new JPanel();
       private JPanel center = new JPanel();
       private JPanel top = new JPanel();
       private JButton approve = new JButton("Approve");
       private JButton review = new JButton("Review");
       private JButton employmentCreate = new JButton("Create/Modify");
       private JLabel PR = new JLabel("Personal Records");
       private JLabel ER = new JLabel("Employment Records");
       private JLabel PerR = new JLabel("Perform Review");
       private JLabel AR = new JLabel("Approve Records");
       private JLabel news = new JLabel("There are no news");
       private JLabel empty = new JLabel();
       private JButton logout = new JButton("Logout");
       private JButton personalCreate = new JButton("Create/Modify");
       private JLabel welcome = new JLabel("Welcome:");
       private JLabel userLbl = new JLabel("USERNAME GOES HERE");
    
       public MainScreen() {
          makeFrame();
       }
    
       private void makeFrame() {
          frame = new JFrame("Main Screen");
          frame.setSize(650, 550);
          frame.setResizable(false);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          // frame.setVisible(true);
          frame.add(panel);
          panel.setLayout(new BorderLayout());
          panel.add(top, BorderLayout.PAGE_START);
          top.add(welcome);
          top.add(userLbl);
          panel.add(left, BorderLayout.LINE_START);
          left.add(news);
          panel.add(center, BorderLayout.CENTER);
          left.setPreferredSize(new Dimension(200, 150));
          center.setLayout(new GridLayout(5, 2));
          center.add(PR);
          center.add(personalCreate);
          personalCreate.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                frame.dispose();
             }
          });
          center.add(ER);
          center.add(employmentCreate);
          employmentCreate.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                frame.dispose();
             }
          });
          center.add(PerR);
          center.add(review);
          center.add(AR);
          center.add(approve);
          center.add(empty);
          center.add(logout);
          frame.setVisible(true);
       }
    }