首先,您应该尽可能避免直接从顶级容器扩展,例如JFrame
。这将您限制在单个使用组件上,例如,您无法在另一个窗口(作为大型组件层次结构的一部分)或小程序上下文中重复使用登录控件。您也没有向类本身添加任何新功能。
您还应该限制推送给用户的窗口数量,因为它很快就会变得混乱。看一眼多个 JFrame 的使用,好/坏实践?更多细节。
相反,您应该考虑使用 MVC (模型-视图-控制器)旨在减少类之间的耦合量以及组件遭受不必要/不需要的修改的风险。
合同(查看)
让我们从定义契约开始,这定义了流程中的每个元素可以做什么、期望做什么以及传递的信息
View
这定义了应用程序中每个视图的核心功能。每个视图可以有一个控制器(由C
)并预计提供JComponent
作为基本表示,用于将视图物理添加到Container
public interface View<C> {
public JComponent getView();
public void setController(C controller);
public C getController();
}
LoginView
这定义了登录视图期望提供哪些信息,在本例中,我们提供用户名和密码信息以及控制器告诉视图登录尝试失败的方法。这允许视图重置视图并在需要时显示错误消息
public interface LoginView extends View<LoginController> {
public String getUserName();
public char[] getPassword();
public void loginFailed(String errorMessage);
}
LoginController
这定义了登录视图的控制器预期发生的预期操作,视图调用它来告诉控制器它应该执行某些操作...
public interface LoginController {
public void performLogin(LoginView view);
public void loginCanceled(LoginView view);
}
ApplicationView
我没有提供这方面的示例,但您可以想象您需要提供您可能希望提供的详细信息,以便感兴趣的各方从视图中提取详细信息。
执行
LoginPane
这是基本的LoginView
执行...
public class LoginPane extends JPanel implements LoginView {
private JTextField userName;
private JPasswordField password;
private JButton okButton;
private JButton cancelButton;
private LoginController controller;
public LoginPane() {
setLayout(new GridBagLayout());
userName = new JTextField(10);
password = new JPasswordField(10);
okButton = new JButton("Ok");
cancelButton = new JButton("Cancel");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.anchor = GridBagConstraints.WEST;
add(new JLabel("User name: "), gbc);
gbc.gridy++;
add(new JLabel("Password: "), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.gridwidth = 2;
add(userName, gbc);
gbc.gridy++;
add(password, gbc);
gbc.gridwidth = 1;
gbc.gridy++;
add(okButton, gbc);
gbc.gridx++;
add(cancelButton, gbc);
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getController().performLogin(LoginPane.this);
}
});
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getController().loginCanceled(LoginPane.this);
}
});
}
@Override
public String getUserName() {
return userName.getText();
}
@Override
public char[] getPassword() {
return password.getPassword();
}
@Override
public void loginFailed(String errorMessage) {
JOptionPane.showMessageDialog(this, errorMessage, "Login failed", JOptionPane.ERROR_MESSAGE);
}
@Override
public void setController(LoginController controller) {
this.controller = controller;
}
@Override
public JComponent getView() {
return this;
}
@Override
public LoginController getController() {
return controller;
}
}
ApplicationPane
基本应用View
public class ApplicationPane extends JPanel implements View {
public ApplicationPane() {
setLayout(new GridBagLayout());
add(new JLabel("Welcome to my awesome application"));
}
@Override
public JComponent getView() {
return this;
}
@Override
public void setController(Object controller) {
// What ever controller you want to use...
}
@Override
public Object getController() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
把它们放在一起......
我们会,这是很多信息,但是你如何使用它呢?
public class CoreApplicationCPane extends JPanel {
protected static final String LOGIN_VIEW = "View.login";
protected static final String APPLICATION_VIEW = "View.application";
private LoginView loginView;
private ApplicationPane applicationView;
private CardLayout cardLayout;
public CoreApplicationCPane() {
cardLayout = new CardLayout();
setLayout(cardLayout);
loginView = new LoginPane();
applicationView = new ApplicationPane();
add(loginView.getView(), LOGIN_VIEW);
add(applicationView.getView(), APPLICATION_VIEW);
loginView.setController(new LoginController() {
@Override
public void performLogin(LoginView view) {
// Do what ever you need to do...
String name = view.getUserName();
char[] password = view.getPassword();
//...
cardLayout.show(CoreApplicationCPane.this, APPLICATION_VIEW);
}
@Override
public void loginCanceled(LoginView view) {
SwingUtilities.windowForComponent(CoreApplicationCPane.this).dispose();
}
});
cardLayout.show(this, LOGIN_VIEW);
}
}
这基本上就是所有东西连接在一起的地方。这LoginView
and ApplicationView
已实例化并添加到主视图,并且控制器已插入。
看一眼:
更多细节。
有关更详细的示例,请查看Java 和 GUI - 根据 MVC 模式,ActionListener 属于哪里?