[英]How MVC work with java swing GUI
Lets say I have a swing GUI which has textfeild and button. 可以说我有一个带有textfeild和button的swing GUI。 When I click button I want to save that value in text in db and return joptionpane "success" message. 当我单击按钮时,我想将该值保存在db中的文本中,并返回joptionpane“成功”消息。
The way I used to do this is 我以前这样做的方式是
Model : JDBC class 型号 :JDBC类
View : GUI : In that button's ' action performed ' action I call save method with parameter. 视图 :GUI :在该按钮的“ 操作已执行 ”操作中,我使用参数调用保存方法。
Controller con = new Controller();
con.save(text1.getText());
Controller : Write a save method. 控制器 :编写保存方法。
JDBC db = new
public void save(jTextfeild text){
text= text1.getText();
boolean b= db.putData("insert into .. values(text)");
if(b){
JOptionPane("Success");
}
}
This is how I started. 这就是我开始的方式。 But later I understood this is not how this should be and this is utterly unsafe and stupid. 但是后来我知道这不是应该的样子,这是完全不安全和愚蠢的。
I really want to learn how to do this in MVC properly. 我真的很想学习如何在MVC中正确执行此操作。 Please be kind enough to explain this to with a small example. 请通过一个小例子对此加以说明。 Thank you for your time. 感谢您的时间。
This is a difficult subject to grasp in something like Swing, which already uses a form of MVC, albeit more like VC-M, where the model is separated from the view and controller, but where the view and controller are combined. 这对于使用Swing之类的东西已经很难理解了,它已经使用了MVC的形式,尽管更像VC-M,其中模型与视图和控制器是分离的,但是视图和控制器是结合在一起的。
Think about a JButton
, you don't supply a controller to manage how it's triggered when a user presses a key or clicks on it with the mouse, this is done internally and you are notified about the actions when the occur. 考虑一下JButton
,您没有提供控制器来管理用户按下键或用鼠标单击键时如何触发它,这是在内部完成的,并且在发生操作时会收到通知。
With this in mind, you need to allow the view to be semi self managed. 考虑到这一点,您需要允许视图是半自我管理的。 For instance, based on your requirements, the view would have a button and text field. 例如,根据您的要求,该视图将具有一个按钮和文本字段。
The view itself would manage the interactions between the user and the button itself (maintain a internal ActionListener
for example), but would then provide notifications to the controller about any state changes that the controller might be interested in. 视图本身将管理用户和按钮本身之间的交互(例如,维护一个内部ActionListener
),但是随后将向控制器提供有关控制器可能感兴趣的任何状态更改的通知。
In a more pure sense of a MVC, the view and model won't know anything about each other and the controller would manage them. 从MVC的角度来看,视图和模型彼此之间一无所知,而控制器将对其进行管理。 This is a little contradictive to how Swing works, as Swing allows you to pass the model directly to the view, see just about any Swing component. 这与Swing的工作方式有点矛盾,因为Swing允许您将模型直接传递到视图,几乎可以看到任何Swing组件。
This doesn't mean that you can't make things work, but you need to know where the concept can falter or needs to be "massaged" to work better. 这并不意味着您无法使事情起作用,而是您需要知道该概念在何处会动摇或需要“按摩”以使其更好地工作。
Normally, when I approach these type of things, I take step back and look at much wider picture, for example. 通常,当我处理这类事情时,我会退后一步,例如看更广阔的前景。
Now, MVC works REALLY well with the concept of "code to interfaces (not implementation)", to that extent, I tend to start with the contracts... 现在,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);
}
Now, one of the requirements of the view is to generate events when the text has changed in some meaningful way, to this end, I've used a simple observer pattern to implement. 现在,视图的要求之一是当文本以某种有意义的方式更改时生成事件,为此,我使用了一种简单的观察者模式来实现。 Now you could argue that the controller is the observer, but to my mind, the controller may have functionality that I don't want to expose to the view (like the model for instance) 现在您可以争辩说控制器是观察者,但是在我看来,控制器可能具有我不想公开给视图的功能(例如模型)
Next comes the model... 接下来是模型...
public interface TextModel {
public String getText();
public void setText(String text);
}
pretty simple really. 真的很简单。 Now, you might consider adding some kind of Exception
to these methods to allow the model the ability to fail for some reason, but the Exception
should be as generic as you can make it (or even a custom Exception
), so that you can replace the implementation should you need to 现在,您可以考虑向这些方法添加某种Exception
,以允许模型由于某种原因而失败,但是Exception
应该与您可以做到的一样通用(甚至是自定义Exception
),以便可以替换您需要执行的操作
And finally, the controller... 最后,控制器...
public interface TextViewController {
public TextView getTextView();
public TextModel getTextModel();
}
again, pretty simple. 再次,非常简单。 You might have a more complex requirement for your controller, but for this example, this is about all we really need. 您可能对控制器有更复杂的要求,但是对于本示例,这就是我们真正需要的。
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);
}
}
}
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;
}
}
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());
}
}
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);
Now, all this is just an example of one possible solution. 现在,所有这些只是一个可能解决方案的示例。 You could have a controller implementation which has a particular implementation of the model or view or both, for example. 例如,您可以具有一个控制器实现,该控制器实现具有模型或视图或两者的特定实现。
The point is, you just shouldn't care. 关键是,您根本不在乎。 The controller doesn't care how the view is implemented, it only cares that it will generate textWasChanged
events. 控制器不在乎视图的实现方式,只在乎它将生成textWasChanged
事件。 The model doesn't care about the view at all (and visa-versa) and the controller doesn't care about model, only that it will get and set some text. 模型根本不关心视图(反之亦然),控制器也不关心模型,只是它会获取并设置一些文本。
For a more complex example, you can have a look at Java and GUI - Where do ActionListeners belong according to MVC pattern? 对于更复杂的示例,您可以看一下Java和GUI-根据MVC模式,ActionListeners在哪里?
SQLException
, as another implementation might not be based on a SQL based solution. 不要在合同中公开实现的详细信息,例如,该模型不应抛出SQLException
,因为另一个实现可能不基于基于SQL的解决方案。 Don't expose UI elements, this means that ALL implementations would then need to implement those elements. 不要公开UI元素,这意味着所有实现都需要实现那些元素。 What happens if I want a implementation of the view that presents a JComboBox
to the user instead of JTextField
? 如果我想实现将JComboBox
呈现给用户而不是JTextField
的视图的实现,该怎么办? This is also the reason I don't use a ActionListener
in the view contract, because I have no idea how a textWasChanged
event might actually be generated by an implementation of the view 这也是我在视图协定中不使用ActionListener
的原因,因为我不知道如何通过视图的实现实际生成textWasChanged
事件
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.