0

I have a JFrame - SuperTest and JPanel - SuperLogin. The login panel has the username and password input fields and a login button. I want it to look like this:

enter image description here

but it looks like the pic below, with input fields having too huge height and width.

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

    }
}

I read that setting min, preferred size would be enough, but it looks like it's not.

enter image description here

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
parsecer
  • 4,758
  • 13
  • 71
  • 140
  • Don't play with minimum and preferred size. Each component should be responsible for determining its own size. – camickr Jul 29 '20 at 18:56

2 Answers2

2

I put everything into a single class. Explanations after the code.

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. All code that deals with the GUI components must run on the Event Dispatch Thread (EDT). Although not mandatory, I like to explicitly launch the EDT by calling EventQueue.invokeLater().
  2. Refer to the Web page with the tutorial on BoxLayout that appears in the other answer.
  3. JTextField and JPasswordField both have a columns property. I find that better for setting a desired width than using setPreferredSize()

Here is a screen capture of the running app.

enter image description here

Abra
  • 19,142
  • 7
  • 29
  • 41
  • Thank you so much! Works perfectly. I realized, however, that I need the `username` and `password` labels too. I managed to add them by uniting the labels and textfields in the extra nested `JPanel`s, but couldn't get it to work with just adding it alongside the textfields. Would it require two `BoxLayout`, side by side, maybe? – parsecer Jul 29 '20 at 19:53
  • @parsecer *I need the username and password labels too.* - use a `GridBagLayout` for all the components. – camickr Jul 29 '20 at 22:23
  • @parsecer I answered the question you asked. It appears you want a different GUI to the one you described in your question. Perhaps you should post a new question? Alternatively, maybe this Q&A will help: https://stackoverflow.com/questions/62964489/how-to-make-my-user-interface-self-adapt-to-the-show-and-hide-of-jpanel/62964801#62964801 – Abra Jul 30 '20 at 05:07
0

From the Oracle docs for 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.

So you just need to set the maximum size.

Charlie Armstrong
  • 2,332
  • 3
  • 13
  • 25