Reputation: 256
I'm creating a Java application using Swing and the MVC design pattern.
The application is designed as follows:
QuizPanel
that extends JPanel
. This panel is the container that holds the main 'Screens' of my application.JPanel
. These JPanel's are added/removed from the QuizPanel
as required.QuizPanel
implements my interface Switchable
. The Switchable
interface consists of a single SwitchView(ViewState state)
method. I pass this
to each 'screen' instantiated in the QuizPanel
top level panel, so they are able to call SwitchView
when a button is pressed.On the login screen, the user enters a pin and student ID, if these match a token in the database, I need to pass the Token
object to another screen of my application (a question screen that I haven't implemented yet) or have it available somehow. The token is retrieved from an embedded Derby database.
The only way I can think of doing this is creating a utility class with static Token
variable that can be accessed by the other classes (this seems like a nasty way to do it). Am I having trouble with this because the design of my application is flawed? Is there any technique I can use to pass the Token
across the different screens of my application?
Main
public static void main(String[] args) {
QuizPanel quizPanel = new QuizPanel();
JFrame frame = new JFrame("Quiz");
frame.setPreferredSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(quizPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
QuizPanel Class
public class QuizPanel extends JPanel implements Switchable{
private MainMenuPane mainMenuPane;
private RegisterPane registerPane;
private LoginPane loginPane;
public QuizPanel() {
setLayout(new BorderLayout());
registerPane = new RegisterPane();
RegisterController registerController = new RegisterController(registerPane, this);
mainMenuPane = new MainMenuPane();
MainMenuController mainMenuController = new MainMenuController(mainMenuPane, this);
loginPane = new LoginPane();
LoginController loginController = new LoginController(loginPane, this);
switchView(ViewState.MAINMENU_STATE);
}
@Override
public void switchView(ViewState state) {
System.out.println("Changing state: " + state);
switch (state) {
case REGISTER_STATE:
removeAll();
setLayout(new BorderLayout());
add(registerPane, BorderLayout.CENTER);
repaint();
revalidate();
break;
case MAINMENU_STATE:
removeAll();
setLayout(new BorderLayout());
add(mainMenuPane, BorderLayout.CENTER);
repaint();
revalidate();
break;
case LOGIN_STATE:
removeAll();
setLayout(new BorderLayout());
add(loginPane, BorderLayout.CENTER);
repaint();
revalidate();
break;
default:
System.out.println("UNREGISTERED STATE!");
break;
}
}
}
Login Controller
public class LoginController implements ILoginController, ILoginViewObserver {
private ILoginView view;
private LoginModel loginModel;
private Switchable parentView;
public LoginController(ILoginView view, Switchable parentView) {
this.view = view;
this.loginModel = new LoginModel();
this.parentView = parentView;
view.addLoginViewObserver(this);
}
@Override
public ILoginView getLoginView() {
return view;
}
@Override
public void submitButtonWasPressed(Token token) {
Token verifiedToken = loginModel.verifyToken(token);
if (verifiedToken != null) {
System.out.println("Token (" + token.token + ") successfully verified");
// How can I pass the token to the new JPanel the parent view will be displaying?
} else {
System.out.println("Token is invalid");
}
}
@Override
public void cancelButtonWasPressed() {
parentView.switchView(ViewState.MAINMENU_STATE);
}
}
LoginModel Class
public class LoginModel {
private List<Token> tokens;
public LoginModel() {
TokenDao tokenAccessObject = new TokenAccessObject();
tokens = tokenAccessObject.getAllTokens();
}
public Token verifyToken(Token providedToken) {
for (Token token : tokens) {
if (token.studentID == providedToken.studentID){
if (token.token.compareTo(providedToken.token) == 0) {
return token;
}
}
}
return null;
}
}
Upvotes: 0
Views: 470
Reputation: 11327
I think that in this case you can use Singleton pattern. This pattern should be used as rarely as possible, but in your case (common information which must be accessed from different classes of application) you can use it (IMHO).
But in your case you can also use one Swing feature.
JComponent
that is laid
out in the window has access to this pane.JComponent
has also possibility to store some user data in a map,
called "client properties". Because JRootPane
extends JComponent
you can store/retrieve your token is this map.Here is a simple code:
public class TokenUtils {
private static final String TOKEN_PROPERTY = "token";
public static Token findToken(JComponent component) {
JRootPane root = component.getRootPane();
if (root != null) {
return Token.class.cast(root.getClientProperty(TOKEN_PROPERTY));
}
return null;
}
public static void putToken(JComponent component, Token token) {
JRootPane root = component.getRootPane();
if (root != null) {
root.putClientProperty(TOKEN_PROPERTY, token);
}
}
}
Important: if you use more than one window, you must put the token into the each of them.
Upvotes: 1
Reputation: 323
A methode to pass the value of the token to the parent JPanel is to add a methode in your interface like setToken(int token) and a global variable in your Quiz panel
QuizPanel:
private int token;
@Override
public void setToken(int token){
this.token = token;
}
Swiched Interface:
public void setToken(int token);
Login:
parentView.setToken(token);
Than you say parentView.setToken(token)
in your LoginController. Now the token variable in the QuizPanel will be set.
Upvotes: 1
Reputation: 18
You could save the token to a file then on the jpanel read that file to get the token
Upvotes: 0