我正在使用Swing和MVC设计模式创建Java应用程序。
该应用程序的设计如下:
有一个扩展了QuizPanel
的类JPanel
。该面板是保存我的应用程序主“屏幕”的容器。
我的应用程序的每个“屏幕”都是扩展JPanel
的单独类。这些JPanel可以根据需要从QuizPanel
添加/删除。
顶级QuizPanel
实现我的接口Switchable
。 Switchable
接口由单个SwitchView(ViewState state)
方法组成。我将this
传递给在QuizPanel
顶级面板中实例化的每个“屏幕”,因此当按下按钮时,他们可以调用SwitchView
。
在登录屏幕上,用户输入密码和学生ID,如果这些ID与数据库中的令牌匹配,则我需要将Token
对象传递到应用程序的另一个屏幕(我尚未实现的问题屏幕)或以某种方式提供它。从嵌入式Derby数据库中检索令牌。
我能想到的唯一方法是创建一个带有静态Token
变量的实用程序类,其他类可以访问该变量(这似乎是一种讨厌的方法)。因为我的应用程序设计有缺陷,我是否对此感到麻烦?我可以使用任何技术在应用程序的不同屏幕之间传递Token
吗?
主要
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类
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;
}
}
}
登录控制器
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类
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;
}
}
最佳答案
我认为在这种情况下,您可以使用Singleton pattern。该模式应尽可能少用,但在您的情况下(必须从不同应用程序类访问的公共信息),您可以使用它(恕我直言)。
但是,您也可以使用一种Swing功能。
任何Swing窗口都有一个根窗格。然后放置的每个JComponent
在窗口中可以访问此窗格。JComponent
还可以在地图中存储一些用户数据,
称为“客户端属性”。因为JRootPane
扩展了JComponent
您可以存储/检索令牌是这张地图。
这是一个简单的代码:
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);
}
}
}
重要提示:如果使用多个窗口,则必须将令牌放入每个窗口中。