Dil*_*Dil 0 java model-view-controller user-interface swing
假设我有一个带有textfeild和按钮的swing GUI.当我单击按钮时,我想将该值保存在db中的文本中并返回joptionpane"success"消息.
我以前的方式是
模型:JDBC类
视图:GUI:在该按钮的" 动作执行 "操作中,我使用参数调用save方法.
Controller con = new Controller();
con.save(text1.getText());
Run Code Online (Sandbox Code Playgroud)
控制器:编写保存方法.
JDBC db = new
public void save(jTextfeild text){
text= text1.getText();
boolean b= db.putData("insert into .. values(text)");
if(b){
JOptionPane("Success");
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我的开始.但后来我明白这不应该是这样的,这是完全不安全和愚蠢的.
我真的想学习如何在MVC中正确地做到这一点.请用一个小例子来解释这个问题.感谢您的时间.
这是一个很难理解的东西,比如Swing,它已经使用了一种MVC形式,虽然更像VC-M,模型与视图和控制器分开,但视图和控制器的组合.
考虑一下JButton
,当用户按下某个键或用鼠标点击它时,你不提供一个控制器来管理它是如何触发的,这是在内部完成的,并且会在发生时通知你.
考虑到这一点,您需要允许视图半自我管理.例如,根据您的要求,视图将具有按钮和文本字段.
视图本身将管理用户与按钮本身之间的交互(ActionListener
例如,维护内部),但随后会向控制器提供有关控制器可能感兴趣的任何状态更改的通知.
在更纯粹的MVC意义上,视图和模型将不会彼此了解任何事情,控制器将管理它们.这与Swing的工作方式有点矛盾,因为Swing允许您将模型直接传递给视图,只需查看任何Swing组件.
这并不意味着你无法让事情发挥作用,但你需要知道这个概念可能会动摇或需要"按摩"才能更好地发挥作用.
通常,当我接近这些类型的东西时,我会退后一步,看看更广泛的画面,例如.
现在,MVC在"代码到接口(不是实现)"的概念下工作得非常好,在这种程度上,我倾向于从合同开始......
public interface TextView {
public void setText(String text);
public String getText();
public void addTextViewObserver(TextViewObserver observer);
public void removeTextViewObserver(TextViewObserver observer);
}
public interface TextViewObserver {
public void textWasChanged(TextView view);
}
Run Code Online (Sandbox Code Playgroud)
现在,视图的一个要求是在文本以某种有意义的方式发生变化时生成事件,为此,我使用了一个简单的观察者模式来实现.现在您可以争辩控制器是观察者,但在我看来,控制器可能具有我不想暴露给视图的功能(例如模型)
接下来是模特......
public interface TextModel {
public String getText();
public void setText(String text);
}
Run Code Online (Sandbox Code Playgroud)
非常简单.现在,您可以考虑Exception
在这些方法中添加某种方法,以允许模型由于某种原因而失败,但Exception
应该像您可以做到的那样(甚至是自定义Exception
),以便您可以替换实现你需要
最后,控制器......
public interface TextViewController {
public TextView getTextView();
public TextModel getTextModel();
}
Run Code Online (Sandbox Code Playgroud)
再次,非常简单.您可能对控制器有更复杂的要求,但对于此示例,这是我们真正需要的.
public class TextViewPane extends JPanel implements TextView {
private JTextField textField;
private JButton updateButton;
private List<TextViewObserver> observers;
public TextViewPane() {
observers = new ArrayList<>(25);
textField = new JTextField(25);
updateButton = new JButton("Update");
updateButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireTextWasChanged();
}
});
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(textField, gbc);
add(updateButton, gbc);
}
@Override
public void setText(String text) {
textField.setText(text);
}
@Override
public String getText() {
return textField.getText();
}
@Override
public void addTextViewObserver(TextViewObserver observer) {
observers.add(observer);
}
@Override
public void removeTextViewObserver(TextViewObserver observer) {
observers.remove(observer);
}
protected void fireTextWasChanged() {
for (TextViewObserver observer : observers) {
observer.textWasChanged(this);
}
}
}
Run Code Online (Sandbox Code Playgroud)
public class SimpleTextModel implements TextModel {
private String text = "This is some text";
@Override
public String getText() {
return text;
}
@Override
public void setText(String text) {
this.text = text;
}
}
Run Code Online (Sandbox Code Playgroud)
public class SimpleTextController implements TextViewController, TextViewObserver {
private TextView view;
private TextModel model;
public SimpleTextController(TextView view, TextModel model) {
this.view = Objects.requireNonNull(view, "TextView can not null");
this.model = Objects.requireNonNull(model, "TextModel can not be null");
view.addTextViewObserver(this);
}
@Override
public TextView getTextView() {
return view;
}
@Override
public TextModel getTextModel() {
return model;
}
@Override
public void textWasChanged(TextView view) {
getTextModel().setText(view.getText());
}
}
Run Code Online (Sandbox Code Playgroud)
TextViewPane view = new TextViewPane();
TextModel model = new SimpleTextModel();
TextViewController controller = new SimpleTextController(view, model);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(view);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Run Code Online (Sandbox Code Playgroud)
现在,所有这些只是一个可能解决方案的一个例子.例如,您可以拥有一个控制器实现,该实现具有模型或视图的特定实现或两者.
关键是,你应该不在乎.控制器不关心视图是如何实现的,它只关心它将生成textWasChanged
事件.该模型根本不关心视图(反之亦然),控制器不关心模型,只是它会得到并设置一些文本.
有关更复杂的示例,您可以查看Java和GUI - ActionListeners根据MVC模式属于哪里?
SQLException
,因为另一个实现可能不基于基于SQL的解决方案.不要暴露UI元素,这意味着所有实现都需要实现这些元素.如果我想要一个JComboBox
向用户呈现的视图的实现而不是JTextField
?这也是我ActionListener
在视图合约中不使用a的原因,因为我不知道textWasChanged
视图的实现如何实际生成事件