-1

I just started learning Swing with a simple code to create login form.

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

}

My code displays header along with Login and Cancel button. But the Labels/Text field (Username and Password) are not been displayed in the panel.

Where am I going wrong?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Ashish
  • 185
  • 1
  • 2
  • 17
  • thats because you have null layout in your JPanel you add them to. use any layoutmanager on your JPanel and it will work. in null layout i guess you have to tell the objects at which position they ahouls be displayed – XtremeBaumer Dec 13 '16 at 07:55
  • Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Dec 13 '16 at 08:51

4 Answers4

3

since everyone is missing the fact of the null layout ill create an answer myself.

inputPanel.setLayout(null);

if you add components to this, you will have to specify the position or you simply use a layoutmanager like BorderLayout or FlowLayout.

inputPanel.setLayout(new FlowLayout());

if you use this you will be able to simply add the components to the JPanel. Also as stated in the other answers, don't add JLabels to other JLables, because the most top one will override the others. With that being said a solution code which should work would looks like this:

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

}
XtremeBaumer
  • 6,275
  • 3
  • 19
  • 65
  • Thanks for the info on Layout. – Ashish Dec 13 '16 at 09:48
  • Also, the piece of code you have given me after editing, needs some changes, like as per your code you have used `FlowLayout()`. Because of this all the elements in the Frame appeared adjacently(like in a single row). Instead of that, I have used `controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 100, 10));` which worked fine for my scenario – Ashish Dec 13 '16 at 09:53
0

You are adding usernameLabel and passwordLabel onto another label inputLabel. [When stacking labels, the topmost label will overwrite and those labels will disappear.] (JLabel on top of another JLabel)! Why don't you add all the labels and fields directly to the mainFrame i.e. the JFrame object?

Community
  • 1
  • 1
officialaimm
  • 378
  • 4
  • 16
0

Here is your solution:

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");
            }
        }
    }
}
Nilesh Jadav
  • 890
  • 9
  • 8
  • you are still having the member variables and don't explain what exactly you did. change these things and you wont get a downvote – XtremeBaumer Dec 13 '16 at 08:46
  • Nilesh, Thanks. this is what I almost needed. – Ashish Dec 13 '16 at 09:59
  • Adding one more thing that when the Layout has been hardcoded with the horizontal and vertical gap, I didnt had to use `setBound` for Label(username and password) – Ashish Dec 13 '16 at 10:02
-1

You are adding Labels/Textfield(Username and Password) to inputLabel which is an instance of JLabel which is not of type of a container.

Change

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

to

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

Also give JTextField a default size, so change

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

to

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

Or you can change the type of inputLabel variable to JPanel and set it a layout like FlowLayout. In this case no need to use setBounds method on components.

Note: that you use the same bounds for multiple components which will make them one on top of another.

  • Jtextfields are displayed even if you don't set any size to them. his problem is that he has null layout on his JPanels. – XtremeBaumer Dec 13 '16 at 08:03
  • Null layout can be used to if he used setBounds method on components.But he set the bounds one on another the same bounds for the components. – Haroon Fuad Dec 13 '16 at 08:08
  • which is the same like specifying the location of the component and setting the size in 1 line – XtremeBaumer Dec 13 '16 at 08:11