我正在开发一个 java 项目,我处理了所有功能,但是当涉及到 GUI 时,我是一个初学者。我想知道的是我可以使用java在一个阶段中显示不同的场景,就像在javaFX中一样吗?例如,我的起点是登录面板,登录后清空 Jframe 并显示下一个 View 或场景。有很多观点我该怎么办?
最佳答案
基本上,在 Swing 中 CardLayout
允许您在单个容器内的 View 之间切换。首先看一下How to Use CardLayout了解更多详情。
以下示例使用 Model-View-Controller方法,旨在同时解耦代码,所以恐怕有点啰嗦,但这是使用 MVC 和代码分离方法的结果(我喜欢接口(interface)编码)
让我们首先定义我们想要的 View ......
public interface IView<C extends IViewController> {
public JComponent getView();
public C getViewController();
}
public interface ILoginView extends IView<ILoginViewController> {
}
public interface IWelcomeView extends IView<IWelcomeViewController> {
}
显然,我们从 View 的基本概念开始,并在此基础上进行构建。每个 View 都有一个 Controller ,它规定每个 View 能够执行的操作...
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);
}
}
现在显然,我们需要能够在 View 之间传递一些数据(在本例中为用户详细信息或“凭据”)
public interface ICredentials {
public String getUserName();
}
现在,让我们了解本质并定义 View 的实际实现...
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
将它们组合在一起,这就是 Controller 发挥作用的地方......
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;
}
}
}
这几乎是“核心”Swing 集成。如果您愿意,只需很少的工作,您就可以使用 JavaFX 中的 Controller 和 View 接口(interface)。
现在所做的就是向用户呈现登录 View ,如果用户成功登录,它会将 View 切换到欢迎 View 并将用户凭据传递给它......
如果您不想复制和粘贴所有这些,这是我用来测试它的一个简单的可运行示例...
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;
}
}
}
}
关于Java应用程序,具有多个场景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29571722/