【问题标题】:Fails to display label and text field in Swing无法在 Swing 中显示标签和文本字段
【发布时间】:2016-12-13 07:34:32
【问题描述】:

我刚开始使用简单的代码来学习 Swing,以创建登录表单。

package swingbeginner;

import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class LoginForm {
    private JFrame mainFrame;
    private JLabel headerLabel;
    private JLabel inputLabel;
    private JPanel inputPanel;
    private JPanel controlPanel;
    private JLabel statusLabel;

    public LoginForm() {
        prepareGUI();
    }

    public static void main(String[] args) {
        LoginForm loginForm = new LoginForm();
        loginForm.loginProcess();
    }

    private void prepareGUI() {
        mainFrame = new JFrame("Login");
        mainFrame.setSize(600, 600);
        mainFrame.setLayout(new FlowLayout());

        headerLabel = new JLabel("",JLabel.CENTER );
        statusLabel = new JLabel("",JLabel.CENTER);   

        statusLabel.setSize(350,100);

        mainFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent windowEvent) {

            }
        });

        inputLabel = new JLabel();
        inputLabel.setLayout(null);

        inputPanel = new JPanel();
        inputPanel.setLayout(null);

        controlPanel = new JPanel();
        controlPanel.setLayout(new FlowLayout());

        mainFrame.add(headerLabel);
        mainFrame.add(inputLabel);
        mainFrame.add(inputPanel);
        mainFrame.add(controlPanel);
        mainFrame.add(statusLabel);
        mainFrame.setVisible(true);
    }

    private void loginProcess() {
        headerLabel.setText("Please Login to Continue!");

        JLabel usernameLabel = new JLabel("Username");
        usernameLabel.setBounds(10,20,80,25);
        JLabel passwordLabel = new JLabel("Password");
        passwordLabel.setBounds(10, 20, 80, 25);

        JTextField usernameTextbox = new JTextField();
        usernameTextbox.setBounds(100,20,165,25);
        JPasswordField passwordTextbox = new JPasswordField();
        passwordTextbox.setBounds(100,20,165,25);

        JButton loginButton = new JButton("Login");
        JButton cancelButton = new JButton("Cancel");

        loginButton.setActionCommand("Login");
        cancelButton.setActionCommand("Cancel");

        loginButton.addActionListener(new ButtonClickListener());
        cancelButton.addActionListener(new ButtonClickListener());

        inputLabel.add(usernameLabel);
        inputPanel.add(usernameTextbox);
        inputLabel.add(passwordLabel);
        inputPanel.add(passwordTextbox);

        controlPanel.add(loginButton);
        controlPanel.add(cancelButton);

        mainFrame.setVisible(true);     
    }


    private class ButtonClickListener implements ActionListener {
        public void actionPerformed(ActionEvent actionEvent) {
            String command = actionEvent.getActionCommand();
            if(command.equals("Login")) {
                statusLabel.setText("Logging In");
            }
            else if(command.equals("Cancel")) {
                statusLabel.setText("Login Cancelled");
            }
        }
    }

}

我的代码显示标题以及登录和取消按钮。但是标签/文本字段(用户名和密码)没有显示在面板中。

我哪里错了?

【问题讨论】:

  • 那是因为您的 JPanel 中有空布局,您将它们添加到其中。在您的 JPanel 上使用任何布局管理器,它都会起作用。在空布局中,我想你必须告诉对象它们应该显示在哪个位置
  • Java GUI 必须在不同的操作系统、屏幕尺寸、屏幕分辨率等上使用不同的语言环境中的不同 PLAF。因此,它们不利于像素完美布局。而是使用布局管理器,或 combinations of them 以及 white space 的布局填充和边框。

标签: java swing


【解决方案1】:

由于每个人都错过了 null 布局的事实,我自己创建一个答案。

inputPanel.setLayout(null);

如果您向其中添加组件,则必须指定位置,或者您只需使用 BorderLayoutFlowLayout 之类的布局管理器。

inputPanel.setLayout(new FlowLayout());

如果您使用它,您将能够简单地将组件添加到JPanel。同样如其他答案所述,不要将JLabels 添加到其他JLables,因为最上面的一个会覆盖其他的。话虽如此,应该可以工作的解决方案代码如下所示:

public class LoginForm {
    private JFrame mainFrame;
    private JLabel headerLabel;
    private JPanel inputPanel;
    private JPanel controlPanel;
    private JLabel statusLabel;

    public LoginForm() {
        prepareGUI();
    }

    public static void main(String[] args) {
        LoginForm loginForm = new LoginForm();
        loginForm.loginProcess();
    }

    private void prepareGUI() {
        mainFrame = new JFrame("Login");
        mainFrame.setSize(600, 600);
        mainFrame.setLayout(new FlowLayout());

        headerLabel = new JLabel("",JLabel.CENTER );
        statusLabel = new JLabel("",JLabel.CENTER);   

        statusLabel.setSize(350,100);

        mainFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent windowEvent) {

            }
        });
        //changes here
        inputPanel = new JPanel();
        inputPanel.setLayout(new FlowLayout());

        controlPanel = new JPanel();
        controlPanel.setLayout(new FlowLayout());

        mainFrame.add(headerLabel);
        mainFrame.add(inputLabel);
        mainFrame.add(inputPanel);
        mainFrame.add(controlPanel);
        mainFrame.add(statusLabel);
        mainFrame.setVisible(true);
    }

    private void loginProcess() {
        headerLabel.setText("Please Login to Continue!");

        JLabel usernameLabel = new JLabel("Username");
        usernameLabel.setBounds(10,20,80,25);
        JLabel passwordLabel = new JLabel("Password");
        passwordLabel.setBounds(10, 20, 80, 25);

        JTextField usernameTextbox = new JTextField();
        usernameTextbox.setBounds(100,20,165,25);
        JPasswordField passwordTextbox = new JPasswordField();
        passwordTextbox.setBounds(100,20,165,25);

        JButton loginButton = new JButton("Login");
        JButton cancelButton = new JButton("Cancel");

        loginButton.setActionCommand("Login");
        cancelButton.setActionCommand("Cancel");

        loginButton.addActionListener(new ButtonClickListener());
        cancelButton.addActionListener(new ButtonClickListener());

        inputPanel.add(usernameLabel); //changes here
        inputPanel.add(usernameTextbox);
        inputPanel.add(passwordLabel);  //changes here
        inputPanel.add(passwordTextbox);

        controlPanel.add(loginButton);
        controlPanel.add(cancelButton);

        mainFrame.setVisible(true);     
    }


    private class ButtonClickListener implements ActionListener {
        public void actionPerformed(ActionEvent actionEvent) {
            String command = actionEvent.getActionCommand();
            if(command.equals("Login")) {
                statusLabel.setText("Logging In");
            }
            else if(command.equals("Cancel")) {
                statusLabel.setText("Login Cancelled");
            }
        }
    }

}

【讨论】:

  • 感谢您提供有关布局的信息。
  • 另外,您在编辑后给我的那段代码需要进行一些更改,例如您使用的代码FlowLayout()。因此,Frame 中的所有元素都相邻出现(就像在单行中一样)。取而代之的是,我使用了controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 100, 10));,它在我的场景中效果很好
【解决方案2】:

这是您的解决方案:

package swingbeginner;

public class LoginForm {

    private JFrame mainFrame;

    private JLabel headerLabel;

    private JLabel inputLabel;

    private JPanel inputPanel;

    private JPanel controlPanel;

    private JLabel statusLabel;

    public LoginForm() {
        prepareGUI();
    }

    public static void main(String[] args) {

        LoginForm loginForm = new LoginForm();
        loginForm.loginProcess();
    }

    private void prepareGUI() {

        mainFrame = new JFrame("Login");
        mainFrame.setSize(600, 600);
        mainFrame.setLayout(new BorderLayout());

        headerLabel = new JLabel("header", JLabel.CENTER);
        statusLabel = new JLabel("status", JLabel.CENTER);

        statusLabel.setSize(350, 100);

        mainFrame.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent windowEvent) {

            }
        });

        controlPanel = new JPanel();
        controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 100, 100));

        mainFrame.add(headerLabel, BorderLayout.NORTH);
        mainFrame.add(controlPanel, BorderLayout.CENTER);
        mainFrame.add(statusLabel, BorderLayout.SOUTH);
        mainFrame.setVisible(true);
    }

    private void loginProcess() {

        headerLabel.setText("Please Login to Continue!");

        JLabel usernameLabel = new JLabel("Username");
        usernameLabel.setBounds(10, 20, 80, 25);
        JLabel passwordLabel = new JLabel("Password");
        passwordLabel.setBounds(10, 20, 80, 25);

        JTextField usernameTextbox = new JTextField(20);
        usernameTextbox.setBounds(100, 20, 165, 25);
        JPasswordField passwordTextbox = new JPasswordField(20);
        passwordTextbox.setBounds(100, 20, 165, 25);

        JButton loginButton = new JButton("Login");
        JButton cancelButton = new JButton("Cancel");

        loginButton.setActionCommand("Login");
        cancelButton.setActionCommand("Cancel");

        loginButton.addActionListener(new ButtonClickListener());
        cancelButton.addActionListener(new ButtonClickListener());

        controlPanel.add(usernameLabel);
        controlPanel.add(usernameTextbox);
        controlPanel.add(passwordLabel);
        controlPanel.add(passwordTextbox);
        controlPanel.add(loginButton);
        controlPanel.add(cancelButton);

        mainFrame.setVisible(true);
    }

    private class ButtonClickListener implements ActionListener {

        public void actionPerformed(ActionEvent actionEvent) {

            String command = actionEvent.getActionCommand();
            if (command.equals("Login")) {
                statusLabel.setText("Logging In");
            }
            else if (command.equals("Cancel")) {
                statusLabel.setText("Login Cancelled");
            }
        }
    }
}

【讨论】:

  • 您仍然拥有成员变量,并且没有解释您到底做了什么。改变这些东西,你就不会被否决
  • 尼莱什,谢谢。这是我几乎需要的。
  • 再添加一件事,当布局已被水平和垂直间隙硬编码时,我不必使用setBound 作为标签(用户名和密码)
【解决方案3】:

您正在将 usernameLabel 和 passwordLabel 添加到另一个标签 inputLabel 上。 [堆叠标签时,最上面的标签将被覆盖,这些标签将消失。](JLabel on top of another JLabel)!为什么不将所有标签和字段直接添加到 mainFrame 即 JFrame 对象?

【讨论】:

    【解决方案4】:

    您正在向 inputLabel 添加标签/文本字段(用户名和密码),这是 JLabel 的一个实例,它不是容器类型。

    改变

    inputLabel.add(usernameLabel);
    inputPanel.add(usernameTextbox);
    inputLabel.add(passwordLabel);
    inputPanel.add(passwordTextbox);
    

    controlPanel.add(usernameLabel);
    controlPanel.add(usernameTextbox);
    controlPanel.add(passwordLabel);
    controlPanel.add(passwordTextbox);
    

    还要给JTextField一个默认大小,所以改

    JTextField usernameTextbox = new JTextField();
    JPasswordField passwordTextbox = new JPasswordField();
    

    JTextField usernameTextbox = new JTextField(20);
    JPasswordField passwordTextbox = new JPasswordField(20);
    

    或者您可以将 inputLabel 变量的类型更改为 JPanel 并将其设置为类似 FlowLayout 的布局。 在这种情况下,不需要在组件上使用 setBounds 方法。

    注意:您对多个组件使用相同的边界,这将使它们一个在另一个之上。

    【讨论】:

    • Jtextfields 会显示,即使您没有为它们设置任何大小。他的问题是他的 JPanel 上的布局为空。
    • 如果他对组件使用 setBounds 方法,则可以使用 Null 布局。但是他将边界设置为与组件相同的边界。
    • 这和指定组件的位置并在1行中设置大小是一样的
    猜你喜欢
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 2018-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多