Java应用程序,具有多个场景

时间:2015-04-10 22:38:03

标签: java swing

我正在研究一个java项目,我处理了所有功能,但是当谈到GUI我是一个初学者。我想知道的是,我可以使用java在一个阶段中显示不同的场景,就像在javaFX中一样吗?例如,我的起点是登录后清空Jframe并显示下一个视图或场景的登录面板。我应该怎么做?

2 个答案:

答案 0 :(得分:1)

基本上,在Swing中CardLayout允许您在单个容器中切换视图。首先,请查看How to Use CardLayout了解详情。

以下示例使用Model-View-Controller方法,旨在同时解耦代码,因此我担心它会长时间啰嗦,但结果却是如此使用MVC和代码分离方法(我喜欢编码到接口)

CardLayout

让我们首先定义我们想要的视图......

public interface IView<C extends IViewController> {

    public JComponent getView();
    public C getViewController();

}

public interface ILoginView extends IView<ILoginViewController> {
}

public interface IWelcomeView extends IView<IWelcomeViewController> {
}

显然,我们从视图的基本概念开始并在其上构建。每个视图都有一个控制器,它决定了每个视图能够做什么......

public interface IViewController {

}

public interface ILoginViewController extends IViewController {

    public void loginWasSuccessful(ICredentials credentials);

    public void loginDidFail();

    public void loginWasCancelled();

}

public interface IWelcomeViewController extends IViewController {

    public ICredentials getCredentials();
    public void setCredentials(ICredentials credentials);

    public void setCredentialsListener(ICredentialsListener listener);
    public ICredentialsListener getCredentialsListener();

    public interface ICredentialsListener {

        public void credentialsWereUpdated(ICredentials credentials);

    }

}

现在显然,我们需要能够在视图之间传递一些数据(在这种情况下是用户详细信息或&#34;凭证&#34;)

public interface ICredentials {

    public String getUserName();

}

现在,让我们了解一下细节并定义视图的实际实现......

public abstract class AbstractView<C extends IViewController> extends JPanel implements IView<C> {

    private C viewController;

    public AbstractView(C viewController) {
        this.viewController = viewController;
    }

    @Override
    public JComponent getView() {
        return this;
    }

    @Override
    public C getViewController() {
        return viewController;
    }

}

public class WelcomeView extends AbstractView<IWelcomeViewController> implements IWelcomeView {

    private JLabel userName;

    public WelcomeView(IWelcomeViewController viewContoller) {
        super(viewContoller);
        viewContoller.setCredentialsListener((ICredentials credentials) -> {
            userName.setText(credentials.getUserName());
            revalidate();
            repaint();
        });

        userName = new JLabel("...");

        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.insets = new Insets(10, 10, 10, 10);

        add(new JLabel("WELCOME!"), gbc);
        add(userName, gbc);

    }

}

public class LoginView extends AbstractView<ILoginViewController> implements ILoginView {

    private JTextField userName;
    private JPasswordField password;

    private JButton login;
    private JButton cancel;

    public LoginView(ILoginViewController controller) {
        super(controller);
        setLayout(new GridBagLayout());

        userName = new JTextField(10);
        password = new JPasswordField(10);

        login = new JButton("Login");
        cancel = new JButton("Cancel");

        login.addActionListener((ActionEvent e) -> {
            // Fake the login process...
            // This might be handed off to another controller...
            String name = userName.getText();
            if (name != null && !name.isEmpty()) {
                Random rnd = new Random();
                if (rnd.nextBoolean()) {
                    getViewController().loginWasSuccessful(new DefaultCredentials(userName.getText()));
                } else {
                    getViewController().loginDidFail();
                }
            }
        });
        cancel.addActionListener((ActionEvent e) -> {
            getViewController().loginWasCancelled();
        });

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(2, 2, 2, 2);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        add(new JLabel("Login"), gbc);

        gbc.gridx = 0;
        gbc.gridy++;
        gbc.gridwidth = 1;
        add(new JLabel("Username:"), gbc);

        gbc.gridy++;
        add(new JLabel("Password:"), gbc);

        gbc.gridx++;
        gbc.gridy = 1;
        add(userName, gbc);

        gbc.gridy++;
        add(password, gbc);

        JPanel controls = new JPanel();
        controls.add(login);
        controls.add(cancel);

        gbc.gridx = 0;
        gbc.gridy++;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        add(controls, gbc);
    }

    public class DefaultCredentials implements ICredentials {

        private final String userName;

        public DefaultCredentials(String userName) {
            this.userName = userName;
        }

        @Override
        public String getUserName() {
            return userName;
        }

    }

}

好的,现在我们已经拥有了所有这些,我们需要通过CardLayout将它们组合在一起,这是控制器发挥作用的地方......

public class MainPane extends JPanel {

    protected static final String LOGIN_VIEW = "View.login";
    protected static final String WELCOME_VIEW = "View.welcome";

    private CardLayout cardLayout;

    private ILoginView loginView;
    private IWelcomeView welcomeView;

    public MainPane() {
        cardLayout = new CardLayout();
        setLayout(cardLayout);

        // This could be established via a factory or builder pattern
        loginView = new LoginView(new LoginViewController());
        welcomeView = new WelcomeView(new WelcomeViewController());

        add(loginView.getView(), LOGIN_VIEW);
        add(welcomeView.getView(), WELCOME_VIEW);

        cardLayout.show(this, LOGIN_VIEW);
    }

    protected class LoginViewController implements ILoginViewController {

        @Override
        public void loginWasSuccessful(ICredentials credentials) {
            welcomeView.getViewController().setCredentials(credentials);
            cardLayout.show(MainPane.this, WELCOME_VIEW);
        }

        @Override
        public void loginDidFail() {
            JOptionPane.showMessageDialog(MainPane.this, "Login vaild", "Error", JOptionPane.ERROR_MESSAGE);
        }

        @Override
        public void loginWasCancelled() {
            SwingUtilities.windowForComponent(MainPane.this).dispose();
        }

    }

    protected class WelcomeViewController implements IWelcomeViewController {

        private IWelcomeViewController.ICredentialsListener credentialsListener;
        private ICredentials credentials;

        @Override
        public ICredentials getCredentials() {
            return credentials;
        }

        @Override
        public void setCredentials(ICredentials credentials) {
            this.credentials = credentials;
            IWelcomeViewController.ICredentialsListener listener = getCredentialsListener();
            if (listener != null) {
                listener.credentialsWereUpdated(credentials);
            }
        }

        @Override
        public void setCredentialsListener(IWelcomeViewController.ICredentialsListener listener) {
            this.credentialsListener = listener;
        }

        @Override
        public IWelcomeViewController.ICredentialsListener getCredentialsListener() {
            return credentialsListener;
        }

    }

}

这几乎是&#34;核心&#34; Swing集成。只需要很少的工作,如果你愿意,可以使用JavaFX中的控制器和视图接口。

现在所有这一切都会向用户显示登录视图,如果用户成功登录,它会将视图切换到欢迎视图并将用户凭据传递给它...

如果你不想复制和粘贴所有这些,这是一个简单的可运行的例子,我用来测试它......

import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestCardLayout {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MainPane extends JPanel {

        protected static final String LOGIN_VIEW = "View.login";
        protected static final String WELCOME_VIEW = "View.welcome";

        private CardLayout cardLayout;

        private ILoginView loginView;
        private IWelcomeView welcomeView;

        public MainPane() {
            cardLayout = new CardLayout();
            setLayout(cardLayout);

            // This could be established via a factory or builder pattern
            loginView = new LoginView(new LoginViewController());
            welcomeView = new WelcomeView(new WelcomeViewController());

            add(loginView.getView(), LOGIN_VIEW);
            add(welcomeView.getView(), WELCOME_VIEW);

            cardLayout.show(this, LOGIN_VIEW);
        }

        protected class LoginViewController implements ILoginViewController {

            @Override
            public void loginWasSuccessful(ICredentials credentials) {
                welcomeView.getViewController().setCredentials(credentials);
                cardLayout.show(MainPane.this, WELCOME_VIEW);
            }

            @Override
            public void loginDidFail() {
                JOptionPane.showMessageDialog(MainPane.this, "Login vaild", "Error", JOptionPane.ERROR_MESSAGE);
            }

            @Override
            public void loginWasCancelled() {
                SwingUtilities.windowForComponent(MainPane.this).dispose();
            }

        }

        protected class WelcomeViewController implements IWelcomeViewController {

            private IWelcomeViewController.ICredentialsListener credentialsListener;
            private ICredentials credentials;

            @Override
            public ICredentials getCredentials() {
                return credentials;
            }

            @Override
            public void setCredentials(ICredentials credentials) {
                this.credentials = credentials;
                IWelcomeViewController.ICredentialsListener listener = getCredentialsListener();
                if (listener != null) {
                    listener.credentialsWereUpdated(credentials);
                }
            }

            @Override
            public void setCredentialsListener(IWelcomeViewController.ICredentialsListener listener) {
                this.credentialsListener = listener;
            }

            @Override
            public IWelcomeViewController.ICredentialsListener getCredentialsListener() {
                return credentialsListener;
            }

        }

    }

    public interface IViewController {

    }

    public interface ILoginViewController extends IViewController {

        public void loginWasSuccessful(ICredentials credentials);

        public void loginDidFail();

        public void loginWasCancelled();

    }

    public interface IWelcomeViewController extends IViewController {

        public ICredentials getCredentials();

        public void setCredentials(ICredentials credentials);

        public void setCredentialsListener(ICredentialsListener listener);

        public ICredentialsListener getCredentialsListener();

        public interface ICredentialsListener {

            public void credentialsWereUpdated(ICredentials credentials);

        }

    }

    public interface ICredentials {

        public String getUserName();
    }

    public interface IView<C extends IViewController> {

        public JComponent getView();

        public C getViewController();

    }

    public interface ILoginView extends IView<ILoginViewController> {
    }

    public interface IWelcomeView extends IView<IWelcomeViewController> {
    }

    public abstract class AbstractView<C extends IViewController> extends JPanel implements IView<C> {

        private C viewController;

        public AbstractView(C viewController) {
            this.viewController = viewController;
        }

        @Override
        public JComponent getView() {
            return this;
        }

        @Override
        public C getViewController() {
            return viewController;
        }

    }

    public class WelcomeView extends AbstractView<IWelcomeViewController> implements IWelcomeView {

        private JLabel userName;

        public WelcomeView(IWelcomeViewController viewContoller) {
            super(viewContoller);
            viewContoller.setCredentialsListener((ICredentials credentials) -> {
                userName.setText(credentials.getUserName());
                revalidate();
                repaint();
            });

            userName = new JLabel("...");

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(10, 10, 10, 10);

            add(new JLabel("WELCOME!"), gbc);
            add(userName, gbc);

        }

    }

    public class LoginView extends AbstractView<ILoginViewController> implements ILoginView {

        private JTextField userName;
        private JPasswordField password;

        private JButton login;
        private JButton cancel;

        public LoginView(ILoginViewController controller) {
            super(controller);
            setLayout(new GridBagLayout());

            userName = new JTextField(10);
            password = new JPasswordField(10);

            login = new JButton("Login");
            cancel = new JButton("Cancel");

            login.addActionListener((ActionEvent e) -> {
                // Fake the login process...
                // This might be handed off to another controller...
                String name = userName.getText();
                if (name != null && !name.isEmpty()) {
                    Random rnd = new Random();
                    if (rnd.nextBoolean()) {
                        getViewController().loginWasSuccessful(new DefaultCredentials(userName.getText()));
                    } else {
                        getViewController().loginDidFail();
                    }
                }
            });
            cancel.addActionListener((ActionEvent e) -> {
                getViewController().loginWasCancelled();
            });

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.insets = new Insets(2, 2, 2, 2);
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(new JLabel("Login"), gbc);

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.gridwidth = 1;
            add(new JLabel("Username:"), gbc);

            gbc.gridy++;
            add(new JLabel("Password:"), gbc);

            gbc.gridx++;
            gbc.gridy = 1;
            add(userName, gbc);

            gbc.gridy++;
            add(password, gbc);

            JPanel controls = new JPanel();
            controls.add(login);
            controls.add(cancel);

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(controls, gbc);
        }

        public class DefaultCredentials implements ICredentials {

            private final String userName;

            public DefaultCredentials(String userName) {
                this.userName = userName;
            }

            @Override
            public String getUserName() {
                return userName;
            }

        }

    }

}

答案 1 :(得分:0)

如果你想要一种不同的方法,我建议学习JavaFX。您可以将StackPane加载到FX场景中(场景是FX对象,而不是您正在谈论的场景),然后将另一个堆栈窗格(您的场景)加载到第一个堆栈窗格中。当您想要更改场景时,您只需从第一个堆栈窗口卸载堆栈窗口并加载另一个窗口。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HelloWorld extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage window) {
        window.setTitle("Hello World!");
        root.getChildren().add(sceneOne);
        Scene scene = new Scene(root, 400, 400);
        window.setScene(scene);
        window.show();
    }

    private StackPane root = new StackPane();
    private MyFirstScene sceneOne = new MyFirstScene();
    private MySecondScene sceneTwo = new MySecondScene();

}

对于MyFirstScene(MySecondScene),您只需扩展StackPane,即可添加所需的所有元素。我建议FX的原因是因为Swing有点贬值而且Oracle使FX取代它。如果您要使用Java制作许多GUI,我会熟悉它。