CardLayout with different sizes

2019-02-24 14:00发布

Well I'm having some troubles by making a CardLayout with different sizes on each card.

After reading The Use of Multiple JFrames: Good or Bad Practice? I noticed I was doing things in a way that is not the apropiate, so I decided to start learning how to use CardLayout

I have tried this answer from @HovercraftFullOfEels

This one from @mKorbel

And finally the answer of @Kleopatra

All of them are based on Hovercraft's answer but with some changes. I was able to create the CardLayout (and still confused about it), and I (in some way) could implement Kleopatra's method, it resizes the frame but not as it should, when copy and pasting the code, you will notice it reduces frame's size just a couple of milimeters (or pixels).

I'm not sure if this is about the Layout managers that I'm using or it is because of I'm not using Kleopatra's methods in the correct way since I also don't know how @Override method works at all or when to use it and when not.

Here's an MCVE (the shortest I could made).

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;

public class PageViewer extends CardLayout{ 
    private static final String loginCard = "login";
    private static final String userCard = "createUser";

    JFrame frame;
    JPanel contentPane;
    CardLayout cardLayout;

    @Override
    public Dimension preferredLayoutSize(Container parent) {
        Component current = findCurrentComponent(parent);
        if (current != null) {
            Insets insets = parent.getInsets();
            Dimension pref = current.getPreferredSize();
            pref.width += insets.left + insets.right;
            pref.height += insets.top + insets.bottom;
            return pref;
        }
        return super.preferredLayoutSize(parent);
    }

    public Component findCurrentComponent(Container parent) {
        for (Component comp : parent.getComponents()) {
            if (comp.isVisible()) {
                return comp;
            }
        }
        return null;
    }

    public void createAndShowUI() {
        frame = new JFrame("Welcome");
        cardLayout = new CardLayout();
        contentPane = new JPanel(cardLayout);

        LoginPage lp = new LoginPage();
        CreateUser cu = new CreateUser();

        lp.register.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e){
                createNewUser();
                frame.pack();
            }
        });

        contentPane.add(lp, loginCard);
        contentPane.add(cu, userCard);

        frame.add(contentPane, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(150, 150);
        frame.pack();
        frame.setResizable(false);
        frame.setVisible(true);
    }

    PageViewer() {
        createAndShowUI();
    }

    public void createNewUser() {
        cardLayout.show(contentPane, userCard);
    }

    public static void main(String[] args) {
        new PageViewer();
    }

    public class LoginPage extends JPanel {
        Image image;
        ImageIcon imageIcon;

        JPanel userPanel;
        JPanel passwordPanel;
        JPanel buttonsPanel;
        JPanel fieldsPanel;

        JFrame frame;

        JLabel usernameLabel;
        JLabel passwordLabel;
        JLabel logo;

        JTextField usernameField;
        JPasswordField passwordField;

        JButton login;
        JButton register;

        public LoginPage() {
            image = Toolkit.getDefaultToolkit().getImage("image.jpg");
            imageIcon = new ImageIcon("image.jpg");

            userPanel = new JPanel();
            passwordPanel = new JPanel();
            buttonsPanel = new JPanel();
            fieldsPanel = new JPanel();

            usernameLabel = new JLabel("username:");
            passwordLabel = new JLabel("password:");
            logo = new JLabel(imageIcon);

            usernameField = new JTextField();
            passwordField = new JPasswordField();

            login = new JButton("Login");
            register = new JButton("Register");

            this.setLayout(new BorderLayout(10, 15));
            this.setBorder(new EmptyBorder(10, 10, 10, 10));
            fieldsPanel.setLayout(new BorderLayout());

            usernameField.setColumns(8);
            passwordField.setColumns(8);

            userPanel.add(usernameLabel);
            userPanel.add(usernameField);

            passwordPanel.add(passwordLabel);
            passwordPanel.add(passwordField);

            fieldsPanel.add(userPanel, BorderLayout.CENTER);
            fieldsPanel.add(passwordPanel, BorderLayout.SOUTH);

            buttonsPanel.add(login);
            buttonsPanel.add(register);

            this.add(logo, BorderLayout.NORTH);
            this.add(fieldsPanel, BorderLayout.CENTER);
            this.add(buttonsPanel, BorderLayout.SOUTH);
        }
    }
    public class CreateUser extends JPanel {
        JPanel userPanel;
        JPanel passPanel;
        JPanel repPassPanel;
        JPanel buttonsPanel;
        JPanel fieldsPanel;

        JLabel username;
        JLabel password;
        JLabel repPassword;

        JTextField userField;
        JPasswordField passField;
        JPasswordField repPassField;

        JButton acceptButton;
        JButton cancelButton;

        public CreateUser() {

            userPanel = new JPanel();
            passPanel = new JPanel();
            repPassPanel = new JPanel();
            buttonsPanel = new JPanel();
            fieldsPanel = new JPanel();

            username = new JLabel("username: ");
            password = new JLabel("password: ");
            repPassword = new JLabel("repeat password: ");

            userField = new JTextField();
            passField = new JPasswordField();
            repPassField = new JPasswordField();

            acceptButton = new JButton("Accept");
            cancelButton = new JButton("Cancel");

            userField.setColumns(8);
            passField.setColumns(8);
            repPassField.setColumns(8);

            userPanel.add(username);
            userPanel.add(userField);

            passPanel.add(password);
            passPanel.add(passField);

            repPassPanel.add(repPassword);
            repPassPanel.add(repPassField);

            buttonsPanel.add(acceptButton);
            buttonsPanel.add(cancelButton);

            fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.Y_AXIS));

            this.setLayout(new BorderLayout(10, 15));
            this.setBorder(new EmptyBorder(10, 10, 10, 10));

            fieldsPanel.add(userPanel);
            fieldsPanel.add(passPanel);
            fieldsPanel.add(repPassPanel);

            this.add(fieldsPanel, BorderLayout.CENTER);
            this.add(buttonsPanel, BorderLayout.SOUTH);
        }
    }
}

So, resuming (and added some more questions that came to my mind while doing the MCVE):

  1. Why the frame isn't resizing as expected?
  2. Am I using the correct Layout managers?
  3. Is my lp.register.addActionListener(... or am I doing it so difficult?

Thanks in advance :)

1条回答
放荡不羁爱自由
2楼-- · 2019-02-24 14:21

Switch the pack and setResizable calls. setResizable will change the border size of the frame on some systems, so instead of

frame.setResizable(false);
frame.pack();

You should be using...

frame.pack();
frame.setResizable(false);

An example of the difference between the calls...

Resizebale

You may also want to actually make use of the PageViewer layout manager...

cardLayout = new PageViewer();

Now, the UI shouldn't be wrapped up in the layout manager like you have it, they should be separated, for example...

CardLayout

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class CardLayoutTest {

    private static final String loginCard = "login";
    private static final String userCard = "createUser";

    private JFrame frame;
    private CardLayout cardLayout;
    private JPanel contentPane;

    public static void main(String[] args) {
        new CardLayoutTest();
    }

    public CardLayoutTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                createAndShowUI();
            }
        });
    }

    public void createAndShowUI() {
        frame = new JFrame("Welcome");
        cardLayout = new PageViewer();
        contentPane = new JPanel(cardLayout);

        LoginPage lp = new LoginPage();
        CreateUser cu = new CreateUser();

        lp.register.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                createNewUser();
                frame.pack();
            }
        });

        contentPane.add(lp, loginCard);
        contentPane.add(cu, userCard);

        frame.add(contentPane, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(150, 150);
        frame.setResizable(false);
        frame.pack();
        frame.setVisible(true);
    }

    public void createNewUser() {
        cardLayout.show(contentPane, userCard);
    }

    public class LoginPage extends JPanel {

        Image image;
        ImageIcon imageIcon;

        JPanel userPanel;
        JPanel passwordPanel;
        JPanel buttonsPanel;
        JPanel fieldsPanel;

        JFrame frame;

        JLabel usernameLabel;
        JLabel passwordLabel;
        JLabel logo;

        JTextField usernameField;
        JPasswordField passwordField;

        JButton login;
        JButton register;

        public LoginPage() {
            image = Toolkit.getDefaultToolkit().getImage("image.jpg");
            imageIcon = new ImageIcon("image.jpg");

            userPanel = new JPanel();
            passwordPanel = new JPanel();
            buttonsPanel = new JPanel();
            fieldsPanel = new JPanel();

            usernameLabel = new JLabel("username:");
            passwordLabel = new JLabel("password:");
            logo = new JLabel(imageIcon);

            usernameField = new JTextField();
            passwordField = new JPasswordField();

            login = new JButton("Login");
            register = new JButton("Register");

            this.setLayout(new BorderLayout(10, 15));
            this.setBorder(new EmptyBorder(10, 10, 10, 10));
            fieldsPanel.setLayout(new BorderLayout());

            usernameField.setColumns(8);
            passwordField.setColumns(8);

            userPanel.add(usernameLabel);
            userPanel.add(usernameField);

            passwordPanel.add(passwordLabel);
            passwordPanel.add(passwordField);

            fieldsPanel.add(userPanel, BorderLayout.CENTER);
            fieldsPanel.add(passwordPanel, BorderLayout.SOUTH);

            buttonsPanel.add(login);
            buttonsPanel.add(register);

            this.add(logo, BorderLayout.NORTH);
            this.add(fieldsPanel, BorderLayout.CENTER);
            this.add(buttonsPanel, BorderLayout.SOUTH);
        }
    }

    public class CreateUser extends JPanel {

        JPanel userPanel;
        JPanel passPanel;
        JPanel repPassPanel;
        JPanel buttonsPanel;
        JPanel fieldsPanel;

        JLabel username;
        JLabel password;
        JLabel repPassword;

        JTextField userField;
        JPasswordField passField;
        JPasswordField repPassField;

        JButton acceptButton;
        JButton cancelButton;

        public CreateUser() {

            userPanel = new JPanel();
            passPanel = new JPanel();
            repPassPanel = new JPanel();
            buttonsPanel = new JPanel();
            fieldsPanel = new JPanel();

            username = new JLabel("username: ");
            password = new JLabel("password: ");
            repPassword = new JLabel("repeat password: ");

            userField = new JTextField();
            passField = new JPasswordField();
            repPassField = new JPasswordField();

            acceptButton = new JButton("Accept");
            cancelButton = new JButton("Cancel");

            userField.setColumns(8);
            passField.setColumns(8);
            repPassField.setColumns(8);

            userPanel.add(username);
            userPanel.add(userField);

            passPanel.add(password);
            passPanel.add(passField);

            repPassPanel.add(repPassword);
            repPassPanel.add(repPassField);

            buttonsPanel.add(acceptButton);
            buttonsPanel.add(cancelButton);

            fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.Y_AXIS));

            this.setLayout(new BorderLayout(10, 15));
            this.setBorder(new EmptyBorder(10, 10, 10, 10));

            fieldsPanel.add(userPanel);
            fieldsPanel.add(passPanel);
            fieldsPanel.add(repPassPanel);

            this.add(fieldsPanel, BorderLayout.CENTER);
            this.add(buttonsPanel, BorderLayout.SOUTH);
        }
    }

    public class PageViewer extends CardLayout {

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            Component current = findCurrentComponent(parent);
            if (current != null) {
                Insets insets = parent.getInsets();
                Dimension pref = current.getPreferredSize();
                pref.width += insets.left + insets.right;
                pref.height += insets.top + insets.bottom;
                return pref;
            }
            return super.preferredLayoutSize(parent);
        }

        public Component findCurrentComponent(Container parent) {
            for (Component comp : parent.getComponents()) {
                if (comp.isVisible()) {
                    return comp;
                }
            }
            return null;
        }
    }
}
查看更多
登录 后发表回答