Java Swing:如何在显示 JFrame 之前实现登录屏幕?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7323086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:31:53  来源:igfitidea点击:

Java Swing: How can I implement a login screen before showing a JFrame?

javaswinguser-interfaceloginjframe

提问by Katherine Rix

I'm trying to make a little game that will first show the player a simple login screen where they can enter their name (I will need it later to store their game state info), let them pick a difficulty level etc, and will only show the main game screen once the player has clicked the play button. I'd also like to allow the player to navigate to a (hopefully for them rather large) trophy collection, likewise in what will appear to them to be a new screen.

我正在尝试制作一个小游戏,该游戏将首先向玩家显示一个简单的登录屏幕,他们可以在其中输入他们的姓名(稍后我将需要它来存储他们的游戏状态信息),让他们选择难度级别等,并且只会一旦玩家点击播放按钮,就会显示主游戏屏幕。我还想让玩家导航到一个(希望对他们来说是相当大的)奖杯收藏,同样在他们看来是一个新屏幕。

So far I have a main game window with a grid layout and a game in it that works (Yay for me!). Now I want to add the above functionality.

到目前为止,我有一个带有网格布局的主游戏窗口和一个可以运行的游戏(对我来说是的!)。现在我想添加上述功能。

How do I go about doing this? I don't think I want to go the multiple JFrame route as I only want one icon visible in the taskbar at a time (or would setting their visibility to false effect the icon too?) Do I instead make and destroy layouts or panels or something like that?

我该怎么做?我不认为我想走多个 JFrame 路线,因为我一次只希望在任务栏中显示一个图标(或者将它们的可见性设置为错误的图标效果?)我应该制作和销毁布局或面板还是类似的东西?

What are my options? How can I control what content is being displayed? Especially given my newbie skills?

我有哪些选择?如何控制显示的内容?特别是考虑到我的新手技能?

回答by Hovercraft Full Of Eels

A simple modal dialog such as a JDialog should work well here. The main GUI which will likely be a JFrame can be invisible when the dialog is called, and then set to visible (assuming that the log-on was successful) once the dialog completes. If the dialog is modal, you'll know exactly when the user has closed the dialog as the code will continue right after the line where you call setVisible(true) on the dialog. Note that the GUI held by a JDialog can be every bit as complex and rich as that held by a JFrame.

一个简单的模态对话框(例如 JDialog)在这里应该可以很好地工作。调用对话框时,可能是 JFrame 的主 GUI 可以不可见,然后在对话框完成后设置为可见(假设登录成功)。如果对话框是模态的,您将确切知道用​​户何时关闭对话框,因为代码将在对话框上调用 setVisible(true) 的行之后继续。请注意,JDialog 拥有的 GUI 可能与 JFrame 拥有的 GUI 一样复杂和丰富。

Another option is to use one GUI/JFrame but swap views (JPanels) in the main GUI via a CardLayout. This could work quite well and is easy to implement. Check out the CardLayout tutorialfor more.

另一种选择是使用一个 GUI/JFrame,但通过 CardLayout 在主 GUI 中交换视图 (JPanels)。这可以很好地工作并且易于实现。查看CardLayout 教程了解更多信息。

Oh, and welcome to stackoverflow.com!

哦,欢迎来到 stackoverflow.com!

回答by Paul Samsotha

Here is an example of a Login Dialog as @HovercraftFullOfEels suggested.

这是@HovercraftFullOfEels 建议的登录对话框示例。

Username: stackoverflowPassword: stackoverflow

用户名:stackoverflow密码:stackoverflow

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

public class TestFrame extends JFrame {

    private PassWordDialog passDialog;

    public TestFrame() {
        passDialog = new PassWordDialog(this, true);
        passDialog.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new TestFrame();
                frame.getContentPane().setBackground(Color.BLACK);
                frame.setTitle("Logged In");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
            }
        });
    }
}

class PassWordDialog extends JDialog {

    private final JLabel jlblUsername = new JLabel("Username");
    private final JLabel jlblPassword = new JLabel("Password");

    private final JTextField jtfUsername = new JTextField(15);
    private final JPasswordField jpfPassword = new JPasswordField();

    private final JButton jbtOk = new JButton("Login");
    private final JButton jbtCancel = new JButton("Cancel");

    private final JLabel jlblStatus = new JLabel(" ");

    public PassWordDialog() {
        this(null, true);
    }

    public PassWordDialog(final JFrame parent, boolean modal) {
        super(parent, modal);

        JPanel p3 = new JPanel(new GridLayout(2, 1));
        p3.add(jlblUsername);
        p3.add(jlblPassword);

        JPanel p4 = new JPanel(new GridLayout(2, 1));
        p4.add(jtfUsername);
        p4.add(jpfPassword);

        JPanel p1 = new JPanel();
        p1.add(p3);
        p1.add(p4);

        JPanel p2 = new JPanel();
        p2.add(jbtOk);
        p2.add(jbtCancel);

        JPanel p5 = new JPanel(new BorderLayout());
        p5.add(p2, BorderLayout.CENTER);
        p5.add(jlblStatus, BorderLayout.NORTH);
        jlblStatus.setForeground(Color.RED);
        jlblStatus.setHorizontalAlignment(SwingConstants.CENTER);

        setLayout(new BorderLayout());
        add(p1, BorderLayout.CENTER);
        add(p5, BorderLayout.SOUTH);
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        addWindowListener(new WindowAdapter() {  
            @Override
            public void windowClosing(WindowEvent e) {  
                System.exit(0);  
            }  
        });


        jbtOk.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (Arrays.equals("stackoverflow".toCharArray(), jpfPassword.getPassword())
                        && "stackoverflow".equals(jtfUsername.getText())) {
                    parent.setVisible(true);
                    setVisible(false);
                } else {
                    jlblStatus.setText("Invalid username or password");
                }
            }
        });
        jbtCancel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setVisible(false);
                parent.dispose();
                System.exit(0);
            }
        });
    }
}

回答by user3097335

I suggest you insert the following code:

我建议您插入以下代码:

JFrame f = new JFrame();
JTextField text = new JTextField(15);   //the 15 sets the size of the text field
JPanel p = new JPanel();
JButton b = new JButton("Login");

f.add(p);   //so you can add more stuff to the JFrame
f.setSize(250,150);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Insert that when you want to add the stuff in. Next we will add all the stuff to the JPanel:

当你想添加东西时插入它。 接下来我们将所有的东西添加到 JPanel:

p.add(text);
p.add(b);

Now we add the ActionListeners to make the JButtons to work:

现在我们添加 ActionListeners 使 JButtons 工作:

b.addActionListener(this);
public void actionPerforemed(ActionEvent e)
{
    //Get the text of the JTextField
    String TEXT = text.getText();
}

Don't forget to import the following if you haven't already:

如果您还没有导入以下内容,请不要忘记导入:

import java.awt.event*;
import java.awt.*;    //Just in case we need it
import java.x.swing.*;

I hope everything i said makes sense, because sometimes i don't (especially when I'm talking coding/Java) All the importing (if you didn't know) goes at the top of your code.

我希望我说的一切都有道理,因为有时我不(尤其是在我谈论编码/Java 时)所有的导入(如果您不知道)都位于代码的顶部。

回答by Serhiy

Instead of adding the game directly to JFrame, you can add your content to JPanel(let's call it GamePanel) and add this panel to the frame. Do the same thing for login screen: add all content to JPanel(LoginPanel) and add it to frame. When your game will start, you should do the following:

JFrame您可以将您的内容添加到JPanel(我们称之为GamePanel)并将此面板添加到框架中,而不是直接将游戏添加到 。对登录屏幕执行相同的操作:将所有内容添加到JPanel( LoginPanel) 并将其添加到框架。当您的游戏开始时,您应该执行以下操作:

  1. Add LoginPanelto frame
  2. Get user input and load it's details
  3. Add GamePaneland destroy LoginPanel(since it will be quite fast to re-create new one, so you don't need to keep it memory).
  1. 添加LoginPanel到框架
  2. 获取用户输入并加载它的详细信息
  3. 添加GamePanel和销毁LoginPanel(因为重新创建一个新的会非常快,所以你不需要保留它的内存)。