我正在研究一个java项目,我处理了所有功能,但是当谈到GUI我是一个初学者。我想知道的是,我可以使用java在一个阶段中显示不同的场景,就像在javaFX中一样吗?例如,我的起点是登录后清空Jframe并显示下一个视图或场景的登录面板。我应该怎么做?
答案 0 :(得分:1)
基本上,在Swing中CardLayout
允许您在单个容器中切换视图。首先,请查看How to Use CardLayout了解详情。
以下示例使用Model-View-Controller方法,旨在同时解耦代码,因此我担心它会长时间啰嗦,但结果却是如此使用MVC和代码分离方法(我喜欢编码到接口)
让我们首先定义我们想要的视图......
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,我会熟悉它。