Search code examples
javaswingjframejbuttonactionlistener

Java GUI - JButton opens another frame from another class


i'm having trouble to get the 2nd frame to display the GUI Components. i've opened the frame using the JButton from the 1st frame.

Here's the screen shot

This is the first frame - ClientModule.java enter image description here

2nd frame - ClientMenu.java enter image description here

Here's the codes i've tried

ClientModule.java

import java.net.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ClientModule extends JFrame implements Runnable{

    private JPanel panel;
    private JFrame frame;
    private JLabel titleLbl, userLbl, passLbl, hostLbl, portLbl, ipLbl;
    private JTextField userTxt, hostTxt, portTxt, ipTxt;
    private JPasswordField passTxt;
    private JButton loginBtn;

    public static void main(String[] args)
    {
        new ClientModule().run();
    }

    public ClientModule()
    {
        frame = new JFrame("DMS(Drawing Message System)");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);

        panel = new JPanel();
        panel.setPreferredSize(new Dimension(500,500));
        panel.setLayout(new FlowLayout());

        titleLbl = new JLabel("LogIn to Drawing Message System(DMS)");
        titleLbl.setFont(new Font("Rockwell Condensed",Font.BOLD,28));      
        userLbl = new JLabel("Username:");
        passLbl = new JLabel("Password:");
        hostLbl = new JLabel("Hostname:");
        portLbl = new JLabel("Port No.:");
        ipLbl = new JLabel("IP Address:");

        userTxt = new JTextField();
        userTxt.setPreferredSize(new Dimension(100,30));

        passTxt = new JPasswordField();
        passTxt.setEchoChar('*');
        passTxt.setPreferredSize(new Dimension(100,30));

        portTxt = new JTextField();
        portTxt.setPreferredSize(new Dimension(100,30));

        ipTxt = new JTextField();
        ipTxt.setPreferredSize(new Dimension(100,30));

        hostTxt = new JTextField();
        hostTxt.setPreferredSize(new Dimension(100,30));

        loginBtn = new JButton("Login!");
        loginBtn.setPreferredSize(new Dimension(90,30));
        loginBtn.addActionListener(new LoginBtnListener());


        panel.add(titleLbl);
        panel.add(userLbl);
        panel.add(userTxt);
        panel.add(passLbl);
        panel.add(passTxt);
        panel.add(hostLbl);
        panel.add(hostTxt);
        panel.add(portLbl);
        panel.add(portTxt);
        panel.add(ipLbl);
        panel.add(ipTxt);
        panel.add(loginBtn);

        frame.add(panel);

    }

    private class LoginBtnListener implements ActionListener
    {
        @SuppressWarnings("deprecation")
        public void actionPerformed(ActionEvent action)
        {
            //thinking this frame will close after ClientMenu's frame is open
            ClientModule client = new ClientModule();
            client.setVisible(false);

            ClientMenu menu = new ClientMenu();
            menu.setVisible(true);
        }
    }

    public void run()
    {
        frame.pack();
        frame.setVisible(true);
    }
}

ClientMenu.java

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.util.*;

public class ClientMenu extends JFrame{

    JFrame frame;
    JPanel panel;
    JLabel titleLbl;
    JButton sendBtn,receiveBtn,logoutBtn;

    public ClientMenu()
    {
        frame = new JFrame("Drawing Message System(DMS)");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);

        panel = new JPanel();
        panel.setLayout(new FlowLayout());
        panel.setPreferredSize(new Dimension(500,500));

        titleLbl = new JLabel("Main Menu");
        titleLbl.setFont(new Font("Rockwell Condensed",Font.BOLD,28));

        sendBtn = new JButton("Send a Drawing");
        sendBtn.setPreferredSize(new Dimension(100,30));

        receiveBtn = new JButton("Receive a Drawing");
        receiveBtn.setPreferredSize(new Dimension(100,30));

        logoutBtn = new JButton("Logout");
        logoutBtn.setPreferredSize(new Dimension(100,30));
        logoutBtn.addActionListener(new LogoutBtnListener());

        panel.add(titleLbl);
        panel.add(sendBtn);
        panel.add(receiveBtn);
        panel.add(logoutBtn);

        frame.add(panel);
    }

    private class LogoutBtnListener implements ActionListener
    {
        //@SuppressWarnings("deprecation")
        public void actionPerformed(ActionEvent action)
        {
            ClientModule client = new ClientModule();
            client.setVisible(true);

            ClientMenu menu = new ClientMenu();
            menu.setVisible(false);
        }
    }

    public static void main(String[] args)
    {
        new ClientMenu().run();
    }

    public void run()
    {
        frame.pack();
        frame.setVisible(true);
    }

}

I'm not sure if i'm missing something, or coded something wrong, or something else. I've already searched and tried.. any help and understanding is appreciated (:


Solution

  • I managed to get the second frame displayed (including its contents) by adding a call to the run() method:

            ClientMenu menu = new ClientMenu();
            menu.setVisible(true);  
            menu.run();
    

    That being said, there are quite some problems with your code:

    1. You have a main method in each of your classes. You should have only 1 main method per application. Since ClientModule seems to be the first Frame you want to have opened, your might want to keep the main method there and remove the one in the other class.

    2. You have a run() method in each class. Personally, I tend to avoid naming methods like this, since it might cause confusion with the run() method which needs to be overridden when dealing with threads. You are clearly attempting to do some multi threading in your ClientModule, but will not work. Please look into this concurrency tutorial to better understand threads. You should also understand that you should never call run() yourself. The tutorial should make that clear.

    3. Swing applications are started a little bit differently that other applications. Please refer to this tutorial for more information.

    4. You have both your classes extend JFrame but then, provide your own. This results in other JFrames being created, which is what happened in my case (I get 2 JFrames per instantiation). If you want your class to behave like a JFrame, consider extending it, if you want to use a JFrame, then compose your class of one, not both (at least not in this case).

    5. Lastly, to get rid of the previous JFrame you could call dispose() on the it. That being said, the approach usually is to use the Card Layout. This would allow you to have 1 frame with multiple content.

    Sorry for the long post, but please consider re factoring as per the above prior to continuing.