Applicazione Java, con più scene

Sto lavorando su un progetto Java, ho gestito ogni funzionalità, ma quando si tratta di GUI sono un principiante. Quello che voglio sapere è che posso usare java per visualizzare scene diverse in una fase come in javaFX? ad es. il mio punto di partenza è un pannello di login dopo il login, svuotare la Jframe e visualizzare la vista o la scena successiva. ci sono molti punti di vista che cosa dovrei fare?

Fondamentalmente, in Swing CardLayout consente di passare da una visualizzazione all’altra all’interno di un singolo contenitore. Inizia dando un’occhiata a Come utilizzare CardLayout per maggiori dettagli.

L’esempio seguente utilizza un approccio Model-View-Controller e ha lo scopo di disaccoppiare il codice allo stesso tempo, quindi temo che sia un po ‘prolisso, ma questo è il risultato dell’utilizzo degli approcci MVC e di separazione del codice (mi piace codifica alle interfacce)

CardLayout

Iniziamo definendo le opinioni che vogliamo …

 public interface IView { public JComponent getView(); public C getViewController(); } public interface ILoginView extends IView { } public interface IWelcomeView extends IView { } 

Ovviamente, iniziamo con un concetto di base di una vista e ci basiamo su di esso. Ogni vista ha un controller, che stabilisce quale sia la capacità di ciascuna vista di …

 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); } } 

Ora ovviamente, dobbiamo essere in grado di passare alcuni dati tra le viste (in questo caso i dettagli dell’utente o “credenziali”)

 public interface ICredentials { public String getUserName(); } 

Ora, passiamo al nocciolo della questione e definiamo le reali implementazioni dei punti di vista …

 public abstract class AbstractView extends JPanel implements IView { 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 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 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; } } } 

Ok, ora abbiamo tutto questo, abbiamo bisogno di raggruppare tutto insieme, attraverso il CardLayout , è qui che entrano in gioco i 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; } } } 

Questa è praticamente l’integrazione “core” di Swing. Con pochissimo lavoro, è ansible utilizzare il controller e visualizzare le interfacce in JavaFX, se lo si desidera.

Ora tutto ciò che fa è la vista di login per l’utente, se l’utente ha effettuato correttamente l’accesso, passerà le visualizzazioni alla vista di benvenuto e le passerà le credenziali dell’utente …

E nel caso in cui non si voglia copiare e incollare tutto ciò, questo è un semplice esempio eseguibile che ho usato per testarlo …

 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 { public JComponent getView(); public C getViewController(); } public interface ILoginView extends IView { } public interface IWelcomeView extends IView { } public abstract class AbstractView extends JPanel implements IView { 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 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 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; } } } } 

Bene, ti suggerirei di imparare JavaFX se vuoi un approccio diverso. Puoi caricare uno StackPane in una scena FX (una scena è un object FX, non una scena come quella di cui stai parlando) e poi caricare un altro stack (la tua scena) nel primo stack. Quando desideri cambiare le scene devi semplicemente scaricare lo stack dal primo e caricarne uno diverso.

 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(); } 

Per MyFirstScene (MySecondScene) estendi semplicemente StackPane e puoi aggiungere tutti gli elementi che desideri. Il motivo per cui sto suggerendo FX è perché Swing è un po ‘deprezzato e Oracle ha fatto FX per sostituirlo. Mi piacerebbe avere familiarità con se stai andando a fare molte GUI utilizzando Java.