Java GUI - JButton 从另一个 class 打开另一个框架

Java GUI - JButton opens another frame from another class

我无法让第二帧显示 GUI 组件。我使用第一帧中的 JButton 打开了框架。

这是屏幕截图

这是第一帧 - ClientModule.java

第 2 帧 - ClientMenu.java

这是我试过的代码

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);
    }

}

我不确定我是否遗漏了什么,或者编码有误,还是其他什么。我已经搜索并尝试过.. 感谢您的帮助和理解 (:

我设法通过添加对 run() 方法的调用来显示第二个框架(包括其内容):

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

话虽这么说,但您的代码存在很多问题:

  1. 您的每个 class 中都有一个 main 方法。每个应用程序应该 只有 1 个主方法。由于 ClientModule 似乎是您想要打开的第一个框架,您可能希望将主要方法保留在那里并删除另一个 class.

  2. 中的方法
  3. 每个 class 中都有一个 run() 方法。就个人而言,我倾向于避免这样命名方法,因为它可能会与 run() 方法混淆,在处理线程时需要重写该方法。您显然正在尝试在 ClientModule 中执行一些多线程操作,但不会起作用。请查看 this 并发教程以更好地理解线程。您还应该明白,您永远不应该 自己给 run() 打电话。教程应该说清楚了。

  4. Swing 应用程序的启动方式与其他应用程序略有不同。详情请参考this教程。

  5. 您有两个 class 和 extend JFrame,但是请提供您自己的。这会导致创建其他 JFrames,这就是我的情况(每个实例化我得到 2 个 JFrames)。如果你想让你的 class 表现得像 JFrame,考虑扩展它,如果你想使用 JFrame,那么将你的 class 组合成一个,而不是两者(至少在这种情况下不是)。

  6. 最后,要摆脱以前的 JFrame,您 可以 对其调用 dispose()。也就是说,该方法通常是使用 Card Layout。这将允许您拥有包含多个内容的 1 帧。

抱歉这么长 post,但请在继续之前考虑按照上述进行重构。

您可以使用 setVisible 属性 到 'true' 或 'false'。