我目前正在编写一个模板Java应用程序,不知何故,如果我想清晰地遵循MVC模式,我不确定ActionListeners属于哪里。
这个示例是基于Swing的,但它不是关于框架的,而是关于Java中MVC的基本概念,使用任何框架来创建GUI。
package controller;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import view.MainView;
public class MainController
{
MainView mainView = new MainView();
public MainController()
{
this.initViewActionListeners();
}
private void initViewActionListeners()
{
mainView.initButtons(new CloseListener());
}
public class CloseListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
mainView.dispose();
}
}
}
查看:
package view;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainView extends JFrame
{
JButton button_close = new JButton();
JPanel panel_mainPanel = new JPanel();
private static final long serialVersionUID = 5791734712409634055L;
public MainView()
{
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setSize(500, 500);
this.add(panel_mainPanel);
setVisible(true);
}
public void initButtons(ActionListener actionListener)
{
this.button_close = new JButton("Close");
this.button_close.setSize(new Dimension(100, 20));
this.button_close.addActionListener(actionListener);
this.panel_mainPanel.add(button_close);
}
}
这是一个很难用Swing回答的问题,因为Swing不是一个纯粹的MVC实现,视图和控制器是混合的。
从技术上讲,模型和控制器应该能够交互,控制器和视图应该能够交互,但是视图和模型不应该交互,这显然不是Swing的工作方式,但这是另一个争论...
另一个问题是,您真的不想向任何人公开UI组件,控制器不应该关心某些操作是如何发生的,只应该关心它们可以发生的。
public interface MainViewListener {
public void didPerformClose(MainView mainView);
}
实际上有两个视图(不考虑实际的对话框),有凭据视图和登录视图,是的,正如您将看到的,它们是不同的。
凭据视图负责收集要进行身份验证的详细信息、用户名和密码。它将向控制器提供信息,让它知道这些凭据何时被更改,因为控制器可能想要采取一些操作,比如启用“登录”按钮...
视图还想知道什么时候要进行身份验证,因为它想要禁用它的字段,这样用户就不能在身份验证进行时更新视图,同样地,它也需要知道身份验证什么时候失败或成功,因为它需要对这些事件采取行动。
public interface CredentialsView {
public String getUserName();
public char[] getPassword();
public void willAuthenticate();
public void authenticationFailed();
public void authenticationSucceeded();
public void setCredentialsViewController(CredentialsViewController listener);
}
public interface CredentialsViewController {
public void credientialsDidChange(CredentialsView view);
}
public class CredentialsPane extends JPanel implements CredentialsView {
private CredentialsViewController controller;
private JTextField userNameField;
private JPasswordField passwordField;
public CredentialsPane(CredentialsViewController controller) {
setCredentialsViewController(controller);
setLayout(new GridBagLayout());
userNameField = new JTextField(20);
passwordField = new JPasswordField(20);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("Username: "), gbc);
gbc.gridy++;
add(new JLabel("Password: "), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(userNameField, gbc);
gbc.gridy++;
add(passwordField, gbc);
DocumentListener listener = new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
getCredentialsViewController().credientialsDidChange(CredentialsPane.this);
}
@Override
public void removeUpdate(DocumentEvent e) {
getCredentialsViewController().credientialsDidChange(CredentialsPane.this);
}
@Override
public void changedUpdate(DocumentEvent e) {
getCredentialsViewController().credientialsDidChange(CredentialsPane.this);
}
};
userNameField.getDocument().addDocumentListener(listener);
passwordField.getDocument().addDocumentListener(listener);
}
@Override
public CredentialsViewController getCredentialsViewController() {
return controller;
}
@Override
public String getUserName() {
return userNameField.getText();
}
@Override
public char[] getPassword() {
return passwordField.getPassword();
}
@Override
public void willAuthenticate() {
userNameField.setEnabled(false);
passwordField.setEnabled(false);
}
@Override
public void authenticationFailed() {
userNameField.setEnabled(true);
passwordField.setEnabled(true);
userNameField.requestFocusInWindow();
userNameField.selectAll();
JOptionPane.showMessageDialog(this, "Authentication has failed", "Error", JOptionPane.ERROR_MESSAGE);
}
@Override
public void authenticationSucceeded() {
// Really don't care, but you might want to stop animation, for example...
}
public void setCredentialsViewController(CredentialsViewController controller){
this.controller = controller;
}
}
public interface LoginView {
public CredentialsView getCredentialsView();
public void willAuthenticate();
public void authenticationFailed();
public void authenticationSucceeded();
public void dismissView();
public LoginViewController getLoginViewController();
}
public interface LoginViewController {
public void authenticationWasRequested(LoginView view);
public void loginWasCancelled(LoginView view);
}
因为LoginPane
将需要根据CredentialsView
中的更改来更改它自己的状态,所以在这种情况下允许LoginPane
充当控制器是有意义的,否则,您需要提供更多的方法来控制按钮的状态,但这会将UI逻辑转移到控制器...
public static class LoginPane extends JPanel implements LoginView, CredentialsViewController {
private LoginViewController controller;
private CredentialsPane credientialsView;
private JButton btnAuthenticate;
private JButton btnCancel;
private boolean wasAuthenticated;
public LoginPane(LoginViewController controller) {
setLoginViewController(controller);
setLayout(new BorderLayout());
setBorder(new EmptyBorder(8, 8, 8, 8));
btnAuthenticate = new JButton("Login");
btnCancel = new JButton("Cancel");
JPanel buttons = new JPanel();
buttons.add(btnAuthenticate);
buttons.add(btnCancel);
add(buttons, BorderLayout.SOUTH);
credientialsView = new CredentialsPane(this);
add(credientialsView);
btnAuthenticate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getLoginViewController().authenticationWasRequested(LoginPane.this);
}
});
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getLoginViewController().loginWasCancelled(LoginPane.this);
// I did think about calling dispose here,
// but's not really the the job of the cancel button to decide what should happen here...
}
});
validateCreientials();
}
public static boolean showLoginDialog(LoginViewController controller) {
final LoginPane pane = new LoginPane(controller);
JDialog dialog = new JDialog();
dialog.setTitle("Login");
dialog.setModal(true);
dialog.add(pane);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
pane.getLoginViewController().loginWasCancelled(pane);
}
});
dialog.setVisible(true);
return pane.wasAuthenticated();
}
public boolean wasAuthenticated() {
return wasAuthenticated;
}
public void validateCreientials() {
CredentialsView view = getCredentialsView();
String userName = view.getUserName();
char[] password = view.getPassword();
if ((userName != null && userName.trim().length() > 0) && (password != null && password.length > 0)) {
btnAuthenticate.setEnabled(true);
} else {
btnAuthenticate.setEnabled(false);
}
}
@Override
public void dismissView() {
SwingUtilities.windowForComponent(this).dispose();
}
@Override
public CredentialsView getCredentialsView() {
return credientialsView;
}
@Override
public void willAuthenticate() {
getCredentialsView().willAuthenticate();
btnAuthenticate.setEnabled(false);
}
@Override
public void authenticationFailed() {
getCredentialsView().authenticationFailed();
validateCreientials();
wasAuthenticated = false;
}
@Override
public void authenticationSucceeded() {
getCredentialsView().authenticationSucceeded();
validateCreientials();
wasAuthenticated = true;
}
public LoginViewController getLoginViewController() {
return controller;
}
public void setLoginViewController(LoginViewController controller) {
this.controller = controller;
}
@Override
public void credientialsDidChange(CredentialsView view) {
validateCreientials();
}
}
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JDialog;
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;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import sun.net.www.protocol.http.HttpURLConnection;
public class Test {
protected static final Random AUTHENTICATION_ORACLE = new Random();
public static void main(String[] args) {
new Test();
}
public interface CredentialsView {
public String getUserName();
public char[] getPassword();
public void willAuthenticate();
public void authenticationFailed();
public void authenticationSucceeded();
public CredentialsViewController getCredentialsViewController();
}
public interface CredentialsViewController {
public void credientialsDidChange(CredentialsView view);
}
public interface LoginView {
public CredentialsView getCredentialsView();
public void willAuthenticate();
public void authenticationFailed();
public void authenticationSucceeded();
public void dismissView();
public LoginViewController getLoginViewController();
}
public interface LoginViewController {
public void authenticationWasRequested(LoginView view);
public void loginWasCancelled(LoginView view);
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
LoginViewController controller = new LoginViewController() {
@Override
public void authenticationWasRequested(LoginView view) {
view.willAuthenticate();
LoginAuthenticator authenticator = new LoginAuthenticator(view);
authenticator.authenticate();
}
@Override
public void loginWasCancelled(LoginView view) {
view.dismissView();
}
};
if (LoginPane.showLoginDialog(controller)) {
System.out.println("You shell pass");
} else {
System.out.println("You shell not pass");
}
System.exit(0);
}
});
}
public class LoginAuthenticator {
private LoginView view;
public LoginAuthenticator(LoginView view) {
this.view = view;
}
public void authenticate() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (AUTHENTICATION_ORACLE.nextBoolean()) {
view.authenticationSucceeded();
view.dismissView();
} else {
view.authenticationFailed();
}
}
});
}
});
t.start();
}
}
public static class LoginPane extends JPanel implements LoginView, CredentialsViewController {
private LoginViewController controller;
private CredentialsPane credientialsView;
private JButton btnAuthenticate;
private JButton btnCancel;
private boolean wasAuthenticated;
public LoginPane(LoginViewController controller) {
setLoginViewController(controller);
setLayout(new BorderLayout());
setBorder(new EmptyBorder(8, 8, 8, 8));
btnAuthenticate = new JButton("Login");
btnCancel = new JButton("Cancel");
JPanel buttons = new JPanel();
buttons.add(btnAuthenticate);
buttons.add(btnCancel);
add(buttons, BorderLayout.SOUTH);
credientialsView = new CredentialsPane(this);
add(credientialsView);
btnAuthenticate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getLoginViewController().authenticationWasRequested(LoginPane.this);
}
});
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getLoginViewController().loginWasCancelled(LoginPane.this);
// I did think about calling dispose here,
// but's not really the the job of the cancel button to decide what should happen here...
}
});
validateCreientials();
}
public static boolean showLoginDialog(LoginViewController controller) {
final LoginPane pane = new LoginPane(controller);
JDialog dialog = new JDialog();
dialog.setTitle("Login");
dialog.setModal(true);
dialog.add(pane);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
pane.getLoginViewController().loginWasCancelled(pane);
}
});
dialog.setVisible(true);
return pane.wasAuthenticated();
}
public boolean wasAuthenticated() {
return wasAuthenticated;
}
public void validateCreientials() {
CredentialsView view = getCredentialsView();
String userName = view.getUserName();
char[] password = view.getPassword();
if ((userName != null && userName.trim().length() > 0) && (password != null && password.length > 0)) {
btnAuthenticate.setEnabled(true);
} else {
btnAuthenticate.setEnabled(false);
}
}
@Override
public void dismissView() {
SwingUtilities.windowForComponent(this).dispose();
}
@Override
public CredentialsView getCredentialsView() {
return credientialsView;
}
@Override
public void willAuthenticate() {
getCredentialsView().willAuthenticate();
btnAuthenticate.setEnabled(false);
}
@Override
public void authenticationFailed() {
getCredentialsView().authenticationFailed();
validateCreientials();
wasAuthenticated = false;
}
@Override
public void authenticationSucceeded() {
getCredentialsView().authenticationSucceeded();
validateCreientials();
wasAuthenticated = true;
}
public LoginViewController getLoginViewController() {
return controller;
}
public void setLoginViewController(LoginViewController controller) {
this.controller = controller;
}
@Override
public void credientialsDidChange(CredentialsView view) {
validateCreientials();
}
}
public static class CredentialsPane extends JPanel implements CredentialsView {
private CredentialsViewController controller;
private JTextField userNameField;
private JPasswordField passwordField;
public CredentialsPane(CredentialsViewController controller) {
setCredentialsViewController(controller);
setLayout(new GridBagLayout());
userNameField = new JTextField(20);
passwordField = new JPasswordField(20);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("Username: "), gbc);
gbc.gridy++;
add(new JLabel("Password: "), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(userNameField, gbc);
gbc.gridy++;
add(passwordField, gbc);
DocumentListener listener = new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
getCredentialsViewController().credientialsDidChange(CredentialsPane.this);
}
@Override
public void removeUpdate(DocumentEvent e) {
getCredentialsViewController().credientialsDidChange(CredentialsPane.this);
}
@Override
public void changedUpdate(DocumentEvent e) {
getCredentialsViewController().credientialsDidChange(CredentialsPane.this);
}
};
userNameField.getDocument().addDocumentListener(listener);
passwordField.getDocument().addDocumentListener(listener);
}
@Override
public CredentialsViewController getCredentialsViewController() {
return controller;
}
@Override
public String getUserName() {
return userNameField.getText();
}
@Override
public char[] getPassword() {
return passwordField.getPassword();
}
@Override
public void willAuthenticate() {
userNameField.setEnabled(false);
passwordField.setEnabled(false);
}
@Override
public void authenticationFailed() {
userNameField.setEnabled(true);
passwordField.setEnabled(true);
userNameField.requestFocusInWindow();
userNameField.selectAll();
JOptionPane.showMessageDialog(this, "Authentication has failed", "Error", JOptionPane.ERROR_MESSAGE);
}
@Override
public void authenticationSucceeded() {
// Really don't care, but you might want to stop animation, for example...
}
public void setCredentialsViewController(CredentialsViewController controller) {
this.controller = controller;
}
}
}
问题内容: 我目前正在编写模板Java应用程序,并且如果我想完全遵循MVC模式,就不确定ActionListener的位置。 该示例基于Swing,但与框架无关,而是Java中使用任何框架创建GUI的MVC的基本概念。 我从一个绝对简单的应用程序开始,该应用程序包含一个JFrame和一个JButton(以放置框架,从而关闭该应用程序)。此帖子后面的代码。没什么特别的,只是为了澄清我们在说什么。我还
我正在用MVC设计模式编写GUI程序。我有一个关于使用ActionListeners的问题。 根据MVC模式,所有ActionListeners都应该包含在Controller中。通常情况下,我相信它们会被实现到内部类中。 然而,如果有许多按钮等,那么将这些内部类移动到同一个包中的单独文件是一个好主意吗?我知道他们将不再是内部类,那么这是一个好的设计吗?由于我需要使用Controller类中的局部
我想要小费。如果您有一个JFrame,其中有许多JPanels,这些JPanels有十个JTextFields标签和一个Edit按钮,那么您将如何构造您的应用程序。 您是将所有代码放在JFrame中,还是从JPanel扩展并将所有代码包含在JFrame中? 纽扣呢?我想使用MVC模式,您将如何处理ActionListeners?是每一个都有一个自己的控制器,还是你只使用一个控制器?
问题内容: 我发现在“真实的Swing生活”中最难掌握的设计模式之一是MVC模式。我浏览了该站点上的很多文章,讨论了该模式,但是我仍然不太清楚如何在Java Swing应用程序中利用该模式。 假设我有一个JFrame,其中包含一个表,几个文本字段和一些按钮。我可能会使用TableModel将JTable与基础数据模型“桥接”。但是,负责清除字段,验证字段,锁定字段以及按钮操作的所有函数通常都直接在
这是要根据模式验证的JSON。 问题是,如果我们传递了错误的数据,它将正确地验证eid和ename的类型(即整数或字符串)。对于例如: 如果我们为限定传递了错误的类型,那么它将验证为true(即,它不验证限定的类型,可能是因为它是嵌套的)。
问题内容: 我知道负载测试应在非GUI模式下运行。 但是, 当我使用以下命令运行测试时: 在非GUI模式下 :我得到的平均响应时间为3到4秒,这当然是不可接受的。 在GUI模式下 :平均响应时间为100ms。 测试非常简单,仅需5秒即可完成100个用户的HTTP请求(GET)。 如果不是这样,我什么也不会说。 我应该信任哪一个? 我的问题更多:发生了什么,如何找到问题? 问题答案: 非GUI模式比