1

I Have recently started Java programming and am trying to create a login screen. However, I cannot figure out how to create a new line to put my buttons and text on. Also, I would like to move these to the bottom right corner of the JPanel. I apologise for my poor wording and hopefully you can see what I mean from my code. Please help and thank you in advance.

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

public class CardLayoutDemo implements ItemListener {
JPanel cards;
final static String BUTTONPANEL = "Card with JButtons";

public void addComponentToPane(Container pane) {

    JPanel card1 = new JPanel();
    card1.add(new JLabel("Username:"));
    card1.add(new JTextField("Username", 10));
    card1.add(new JButton("Login")); //end line here
    //New line
    card1.add(new JLabel("Password:"));
    card1.add(new JTextField("Password", 10));
    card1.add(new JButton("Register")); //end line here
    //New line
    card1.add(new JCheckBox());
    card1.add(new JLabel("Remember credentials"));


    cards = new JPanel(new CardLayout());
    cards.add(card1, BUTTONPANEL);

    pane.add(cards, BorderLayout.BOTTOM_RIGHT);// Add cards to bottom right hand corner.
}

public void itemStateChanged(ItemEvent evt) {
    CardLayout cl = (CardLayout)(cards.getLayout());
    cl.show(cards, (String)evt.getItem());
}

private static void createAndShowGUI() {
    JFrame frame = new JFrame("Login");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    CardLayoutDemo demo = new CardLayoutDemo();
    demo.addComponentToPane(frame.getContentPane());

    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {

    try {

        UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
    } catch (UnsupportedLookAndFeelException ex) {
        ex.printStackTrace();
    } catch (IllegalAccessException ex) {
        ex.printStackTrace();
    } catch (InstantiationException ex) {
        ex.printStackTrace();
    } catch (ClassNotFoundException ex) {
        ex.printStackTrace();
    }

    UIManager.put("swing.boldMetal", Boolean.FALSE);

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}
}
Auspexis
  • 69
  • 1
  • 4
  • 11
  • 1
    This won't compile on my Java 6 system; BorderLayout.BOTTOM_RIGHT is not recognized. If I change BOTTOM_RIGHT to PAGE_END, I get your controls at the bottom of the screen, centered on the frame. Unfortunately I cannot tell for sure what you want, and your code only has what you've done, not what you want done. Do you want the username and password on different lines, is that it? – arcy Oct 27 '13 at 17:04
  • I know that BOTTOM_RIGHT is not a correct command, I was just using it as an example. Yes, you hit the nail on the head, that is exactly what i want. – Auspexis Oct 27 '13 at 18:35
  • +1 for update and [sscce](http://sscce.org/), modulo the comment by @rcook. – trashgod Oct 27 '13 at 19:46

3 Answers3

5

As shown here, you can position your top-level container in the lower, right portion of the screen. Substitute your own components for the placeholder mentioned in getPreferredSize(). Also, consider a JToolBar, which can float on many implementations.

Addendum: I want to move the buttons to the bottom right corner of the JPanel, not move the JPanel to the bottom of the screen.

Specifying FlowLayout.RIGHT for your card1 produces the result shown. Substitute your panel having CardLayout in the content pane's BorderLayout.CENTER.

image

public void addComponentToPane(Container pane) {

    JPanel card1 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
    …
    pane.add(new JPanel() {
        @Override // placeholder for actual content
        public Dimension getPreferredSize() {
            return new Dimension(800, 200);
        }
    }, BorderLayout.CENTER);
    pane.add(cards, BorderLayout.PAGE_END);
}

Addendum: Here's an update to your example.

public void addComponentToPane(Container pane) {
    …
    pane.add(cards, BorderLayout.PAGE_END);
}
…
private static void createAndShowGUI() {
    JFrame frame = new JFrame("Login");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // Move frame to lower right corner of screen
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice defaultScreen = ge.getDefaultScreenDevice();
    Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds();
    int x = (int) rect.getMaxX() - frame.getWidth();
    int y = (int) rect.getMaxY() - frame.getHeight();
    frame.setLocation(x, y);

    CardLayoutDemo demo = new CardLayoutDemo();
    demo.addComponentToPane(frame.getContentPane());

    frame.pack();
    frame.setVisible(true);
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Sorry, I know I did not make it clear. I want to move the buttons to the bottom right corner of the JPanel, not move the JPanel to the bottom of the screen. – Auspexis Oct 27 '13 at 18:37
  • Thank you, this worked perfectly, sorry I did not respond earlier. – Auspexis Oct 27 '13 at 19:36
  • Sorry, but is there any way to add line breaks so that username & login are on one line, Password and register are on the second, and remember credentials are on the third? Something like the
    tag in HTML. I have heard about containers, is this the way to go or is there another, easier way.
    – Auspexis Oct 27 '13 at 20:05
  • Yes, create a `JPanel` having `Gridlayout` and add as many right-aligned row panels as needed; add the grid to `SOUTH`; . – trashgod Oct 27 '13 at 23:41
3

Suggestion:

  1. There is no such constraint BorderLayout.BOTTOM_RIGHT with BorderLayout.

    • BorderLayout.SOUTH : place the component at the bottom of container
    • BorderLayout.EAST : Place the component at the right side of container
    • BorderLayout.NORTH : place the component at the top of container
    • BorderLayout.WEST : place the component at the right side of container
    • BorderLayout.CENTER: place the component at the middle of container

    If you want to orient your component as you wish, where the component will appear in order, positioned in relative to each other, responsive with Main Container's re-size, the you need to learn about Layout Manager first.

  2. Learn about Event listeners. Instead of implementing an ItemListener to a JPanel/Top level class which doesn't have such listeners, either implement it to a new class with naming convention MyItemListener implements ItemListener and create a new instance to add with addItemListener(listener) function or add them inline using the means of anonymous class.

     checkBox.addItemListener(new ItemListener() {
    
        @Override
        public void itemStateChanged(ItemEvent e) {
           // put your code
        }
    });
    

    ItemListener is for the Components which works with item i.e CheckBox, ComboBox etc. There are other kind of Even listeners exist too e.g, ActionListener, MouseListener etc

Tutorial Resource:

  1. Writing Event Listeners
  2. Using Layout Managers
Sage
  • 15,290
  • 3
  • 33
  • 38
  • Your second point doesn't make sense. One can write event listener where one wishes. It can be anonymous or any class implementing listeners. It can be extended JPanel too! – nullptr Oct 27 '13 at 17:24
  • When we work with component it is general rule that we use the listeners that reflect the use with that component. Implementing an itemlistner doesn't make sense because panel doesn't have such listeners. We can define A class of animal `Fish` with property `Leg` and function `walk()` if we wish to, but defining such is nonsense – Sage Oct 27 '13 at 17:40
  • Well, OP is not implementing ItemListener in JPanel, OP is implementing ItemListener in CardLayoutDemo. – nullptr Oct 27 '13 at 17:58
  • Class can implement listeners and it can be container for child components too. One can use checkbox.addItemListener(this). – nullptr Oct 27 '13 at 18:01
  • It is not preferable to be implementing a DEMO with Listeners either. If the component is checkBox then yes it is ok implementing it to a `CheckBox` extending class. But it is always preferable to use an inline adding listener with `addXXXListener(new XXXListener(){})`, it makes the code more readable and clean. Well you can say preferable doesn't mean rule, but if it is good practice why not making it a rule – Sage Oct 27 '13 at 18:06
  • From OP's code i can understand that he has started learning. If someone with advanced programming knowledge wrote that code, i would have looked over thinking that he did it to prepare a demo in short hand. But for a new learner doing these practice is obvious while they don't even know which one is good(preferable) and which one is bad practice – Sage Oct 27 '13 at 18:08
1

I've taken your code and modified it to the following:

package sandbox;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class LoginLayoutDemo
{
    JPanel cards;

    public void addComponentToPane(Container pane)
    {
        // Panel for text and fields
        JPanel textAndFieldsPanel = new JPanel();
        textAndFieldsPanel.setLayout(new GridLayout(2,2));
        textAndFieldsPanel.add(new JLabel("Username ", JLabel.RIGHT));
        textAndFieldsPanel.add(new JTextField("Username", 10));
        textAndFieldsPanel.add(new JLabel("Password ", JLabel.RIGHT));
        textAndFieldsPanel.add(new JPasswordField("password", 10));

        JPanel controlsPanel = new JPanel();
        controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.PAGE_AXIS));

        controlsPanel.add(textAndFieldsPanel);
        controlsPanel.add(new JCheckBox("Remember credentials"));

        JPanel bottomPanel = new JPanel();

        bottomPanel.add(controlsPanel);
        bottomPanel.add(new JButton("Login")); // end line here

        bottomPanel.add(new JButton("Register")); // end line here

        cards = new JPanel(new BorderLayout());
//      cards.setLayout(new BorderLayout(cards, BoxLayout.LINE_AXIS));
        cards.add(bottomPanel, BorderLayout.LINE_END);

        pane.add(cards, BorderLayout.PAGE_END);   // BOTTOM_RIGHT);// Add cards to bottom right hand
                                                                                                // corner.
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("Login");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//      CardLayoutDemo demo = new CardLayoutDemo();
        new LoginLayoutDemo().addComponentToPane(frame.getContentPane());

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {

        try
        {

            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
        } catch (UnsupportedLookAndFeelException ex)
        {
            ex.printStackTrace();
        } catch (IllegalAccessException ex)
        {
            ex.printStackTrace();
        } catch (InstantiationException ex)
        {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex)
        {
            ex.printStackTrace();
        }

        UIManager.put("swing.boldMetal", Boolean.FALSE);

        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

You really need to learn about LayoutManagers -- the Oracle/Java site has a decent one, and there are others readily available. The thing I think most of them do least well is explain overall what the managers are for and how to design things with them - they tend to plunge right into code.

A LayoutManager is applied to a Container, and tells it how to treat the components that are added to it. FlowLayout and BoxLayout tend to lay things out in a line, either horizontal or vertical at your choice. GridLayout lays things out in a table, with all 'cells' in the grid the same size. BorderLayout has a center section and one section each for N, S, E, and W; N,S stretch horizontally, E,W stretch vertically; all four of these take their other dimension from their contained component, and the center of the BorderLayout stretches in both directions to fill the available space in its container. There is GroupLayout and GridBagLayout, etc., they are all designed to solve some problem or set of problems in UI design, and you need to learn what they do in order to design Swing UIs.

Something that some of the tutorials do but don't really explain: Each container has one layout manager, but the container can be a component in another container, and the enclosing container can have a different layout manager. That's what we've done here; the BorderLayout of the overall frame puts the panel we've built at the bottom, and the right-aligned panel within our panel puts them to the right; that's how they all get to the bottom right.

You may have meant for others of your controls to be on other lines; I'll leave doing that as an exercise for you... Good luck.

One more thing: CardLayout is for situations is where, for some reason, two or more panels are arranged on TOP of each other, i.e., one obscures the other. You have no such need in your UI that I could tell, so I eliminated the CardLayout manager.

arcy
  • 12,845
  • 12
  • 58
  • 103