Java 与父JPanel通信
我正在使用Swing和MVC设计模式创建一个Java应用程序 该应用程序的设计如下:Java 与父JPanel通信,java,swing,oop,Java,Swing,Oop,我正在使用Swing和MVC设计模式创建一个Java应用程序 该应用程序的设计如下: 有一个类QuizPanel扩展了JPanel。此面板是保存我的应用程序的主“屏幕”的容器 我的应用程序的每个“屏幕”都是一个单独的类,它扩展了JPanel。这些JPanel根据需要从QuizPanel中添加/删除 顶级的QuizPanel实现了我的界面可切换。Switchable界面由一个SwitchView(ViewState状态)方法组成。我将此传递到QuizPanel顶层面板中实例化的每个“屏幕”,这样
- 有一个类
扩展了QuizPanel
。此面板是保存我的应用程序的主“屏幕”的容器JPanel
- 我的应用程序的每个“屏幕”都是一个单独的类,它扩展了
。这些JPanel根据需要从JPanel
中添加/删除QuizPanel
- 顶级的
实现了我的界面QuizPanel
。可切换
界面由一个Switchable
方法组成。我将此SwitchView(ViewState状态)
传递到
顶层面板中实例化的每个“屏幕”,这样当按下按钮时,他们就可以调用QuizPanel
SwitchView
令牌
对象传递到我的应用程序的另一个屏幕(我尚未实现的问题屏幕)或以某种方式使其可用。令牌从嵌入式Derby数据库中检索
我能想到的唯一方法是创建一个带有静态Token
变量的实用程序类,其他类可以访问该类(这似乎是一种令人讨厌的方法)。我是否因为我的应用程序设计有缺陷而在这方面遇到问题?是否有任何技术可以用于在应用程序的不同屏幕之间传递令牌
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类
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 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;
}
}
登录控制器
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);
}
}
登录模型类
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 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;
}
}
公共类登录模型{
私有列表令牌;
公共登录模型(){
TokenDao tokenAccessObject=新的tokenAccessObject();
tokens=tokenAccessObject.getAllTokens();
}
公共令牌验证令牌(令牌提供令牌){
for(令牌:令牌){
if(token.studentID==providedToken.studentID){
if(token.token.compareTo(providedToken.token)==0){
返回令牌;
}
}
}
返回null;
}
}
您可以将令牌保存到文件中,然后在jpanel上读取该文件以获取令牌您可以将令牌保存到文件中,然后在jpanel上读取该文件以获取令牌将令牌的值传递给父jpanel的方法是在接口中添加一个方法,如setToken(int-token)在你的测试面板中有一个全局变量
QuizPanel:
private int token;
@Override
public void setToken(int token){
this.token = token;
}
切换界面:
public void setToken(int token);
登录:
parentView.setToken(token);
然后在LoginController中说
parentView.setToken(token)
。现在将设置QuizPanel中的token变量 将令牌值传递给父JPanel的方法是在接口中添加一个方法,如setToken(int-token)和测验面板中的一个全局变量
QuizPanel:
private int token;
@Override
public void setToken(int token){
this.token = token;
}
切换界面:
public void setToken(int token);
登录:
parentView.setToken(token);
然后在LoginController中说
parentView.setToken(token)
。现在将设置QuizPanel中的token变量 我认为在这种情况下,您可以使用。应该尽可能少地使用此模式,但在您的情况下(必须从不同应用程序类访问的公共信息),您可以使用它(IMHO)
但在您的情况下,您也可以使用一个Swing功能
j组件
在窗口外可以访问此窗格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);
}
}
}
重要:如果您使用多个窗口,则必须将令牌放入每个窗口。我认为在这种情况下,您可以使用。应该尽可能少地使用此模式,但在您的情况下(必须从不同应用程序类访问的公共信息),您可以使用它(IMHO) 但在您的情况下,您也可以使用一个Swing功能
j组件
在窗口外可以访问此窗格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);
}
}
}
重要信息:如果您使用多个窗口,则必须将令牌放入每个窗口中。谢谢您的回答,但令牌已与其他一些窗口一起存储在数据库中,我认为可能会有更面向对象的解决方案。我会在另一个视图中从数据库中检索它,但我需要用户的凭据来知道要检索哪一个。感谢您的回答,但是令牌已经与其他一些令牌一起存储在数据库中,我认为可能有一个更面向对象的解决方案。我想从另一个视图的数据库中检索它,但我需要用户的凭据来知道要检索哪个。谢谢您的回答。我考虑过这样做。问题是,我需要在我的应用程序的不同面板中提供这些信息。我不想在需要访问对象的每个JPanel的构造函数中传递
令牌
对象的实例。谢谢您的回答。我考虑过这样做。问题是,我需要在我的应用程序的不同面板中提供这些信息。我不想在需要访问对象的每个JPanel的构造函数中传递令牌
对象的实例。感谢您的建议!这就是我要找的,太好了。谢谢你的建议!这就是我要找的