BoxLayout:无法设置 child 组件大小

BoxLayout: can't setup child component size

我有一个 JFrame - SuperTestJPanel - SuperLogin。登录面板有用户名和密码输入字段和一个登录按钮。我希望它看起来像这样:

但它看起来像下图,输入字段的高度和宽度太大。

SuperTest.java:

import javax.swing.*;

public class SuperTest extends JFrame {
    public SuperTest()  {
        add(new SuperLogin());
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(600, 400);
    }

    public static void main(String[] args) {
        SuperTest test = new SuperTest();
    }
}

SuperLogin.java:

import javax.swing.*;
import java.awt.*;

public class SuperLogin extends JPanel {
    private JButton loginButton =
            new JButton("Login");
    private TextField usernameField =
            new TextField();
    private TextField passwordField =
            new TextField();

    public SuperLogin()  {
        BoxLayout layout =
                new BoxLayout(this, BoxLayout.Y_AXIS);
        setLayout(layout);

        add(new JLabel("Login"));

        add(usernameField);
        add(passwordField);
        add(loginButton);

        componentSetup();
    }

    private void componentSetup()  {
        loginButton.setSize(20, 10);
        usernameField.setSize(100, 50);
        passwordField.setSize(100, 50);

        loginButton.setMinimumSize(new Dimension(20, 10));
        usernameField.setMinimumSize(new Dimension(100, 50));
        passwordField.setMinimumSize(new Dimension(100, 50));

        loginButton.setPreferredSize(new Dimension(20, 10));
        usernameField.setPreferredSize(new Dimension(100, 50));
        passwordField.setPreferredSize(new Dimension(100, 50));

    }
}

我读到设置最小,首选大小就足够了,但看起来不够。

来自 Oracle docs 的 BoxLayout:

What if none of the components has a maximum width? In this case, if all the components have identical X alignment, then all components are made as wide as their container.

所以你只需要设置最大尺寸即可。

我把所有东西都放在一个class中。代码后的解释。

import java.awt.Component;
import java.awt.EventQueue;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class SuperOne implements Runnable {
    private JButton  loginButton;
    private JFrame  frame;
    private JPasswordField  passwordField;
    private JTextField  usernameField;

    @Override
    public void run() {
        showGui();
    }

    private JPanel createLoginPanel() {
        JPanel loginPanel = new JPanel();
        BoxLayout layout = new BoxLayout(loginPanel, BoxLayout.PAGE_AXIS);
        loginPanel.setLayout(layout);
        loginPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        JLabel loginLabel = new JLabel("Login");
        loginLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        usernameField = new JTextField(10);
        usernameField.setAlignmentX(Component.CENTER_ALIGNMENT);
        passwordField = new JPasswordField(10);
        passwordField.setAlignmentX(Component.CENTER_ALIGNMENT);
        loginButton = new JButton("login");
        loginButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        loginPanel.add(loginLabel);
        loginPanel.add(Box.createVerticalStrut(15));
        loginPanel.add(usernameField);
        loginPanel.add(Box.createVerticalStrut(5));
        loginPanel.add(passwordField);
        loginPanel.add(Box.createVerticalStrut(5));
        loginPanel.add(loginButton);
        return loginPanel;
    }

    private void showGui() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(createLoginPanel());
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    /**
     * Start here.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new SuperOne());
    }
}
  1. 所有处理 GUI 组件的代码必须 运行 在 事件调度线程 (EDT) 上。虽然不是强制性的,但我喜欢通过调用 EventQueue.invokeLater().
  2. 来明确启动 EDT
  3. 请参阅 中出现的有关 BoxLayout 教程的网页。
  4. JTextFieldJPasswordField 都有一个 属性。我发现设置所需宽度比使用 setPreferredSize()
  5. 更好

这是 运行ning 应用程序的屏幕截图。