MVC 如何与 java swing GUI 配合使用 [英] How MVC work with java swing GUI

查看:34
本文介绍了MVC 如何与 java swing GUI 配合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个带有文本字段和按钮的摆动 GUI.当我单击按钮时,我想将该值保存在 db 中的文本中并返回 joptionpane成功"消息.
我以前这样做的方式是
模型:JDBC 类
View:GUI:在那个按钮的动作执行"动作中,我调用带有参数的保存方法.

Lets say I have a swing GUI which has textfeild and button. When I click button I want to save that value in text in db and return joptionpane "success" message.
The way I used to do this is
Model : JDBC class
View : GUI : In that button's 'action performed' action I call save method with parameter.

   Controller con = new Controller();
   con.save(text1.getText());

Controller:编写一个保存方法.

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"); 
   }
 }


我就是这样开始的.但后来我明白这不应该是这样,这是完全不安全和愚蠢的.
我真的很想学习如何在 MVC 中正确地做到这一点.请用一个小例子来解释这一点.感谢您的时间.


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. Please be kind enough to explain this to with a small example. Thank you for your time.

推荐答案

这是一个很难掌握的主题,比如 Swing,它已经使用了 MVC 的形式,尽管更像 VC-M,其中模型与视图和控制器,但是视图和控制器组合在一起.

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.

考虑一个 JButton,当用户按下一个键或用鼠标点击它时,你没有提供一个控制器来管理它是如何触发的,这是在内部完成的,你会收到通知发生时的动作.

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.

考虑到这一点,您需要允许视图进行半自我管理.例如,根据您的要求,视图会有一个按钮和文本字段.

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.

视图本身会管理用户和按钮本身之间的交互(例如维护一个内部的ActionListener),但随后会向控制器提供有关控制器可能发生的任何状态更改的通知有兴趣.

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.

在更纯粹的 MVC 意义上,视图和模型不会相互了解任何信息,控制器将管理它们.这与 Swing 的工作方式有点矛盾,因为 Swing 允许您将模型直接传递给视图,几乎可以查看任何 Swing 组件.

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. 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.

这并不意味着你不能让事情发挥作用,但你需要知道这个概念在哪里会动摇或需要按摩"才能更好地工作.

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.

  • 您有一个可以接受文本并生成文本或对其进行更改的视图
  • 您有一个可以加载和修改文本的模型,但几乎不提供其他事件
  • 您有一个控制器想要从模型中获取文本并将其提供给视图并监视视图对文本的更改并在模型中更新它们

现在,MVC 非常适合代码到接口(而非实现)"的概念,在这种情况下,我倾向于从合同开始......

Now, MVC works REALLY well with the concept of "code to interfaces (not implementation)", to that extent, I tend to start with the contracts...

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)

接下来是模型...

public interface TextModel {
    public String getText();
    public void setText(String text);
}

其实很简单.现在,您可能会考虑向这些方法添加某种 Exception 以允许模型因某种原因而失败,但是 Exception 应该尽可能通用它(甚至是自定义的Exception),以便您可以在需要时替换实现

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

最后,控制器...

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.

关键是,你不应该在意.控制器并不关心视图是如何实现的,它只关心它会生成 textWasChanged 事件.模型根本不关心视图(反之亦然),控制器也不关心模型,只关心它会获取和设置一些文本.

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. 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.

更复杂的例子,你可以看看Java 和 GUI - 根据 MVC 模式,ActionListeners 属于哪里?

For a more complex example, you can have a look at Java and GUI - Where do ActionListeners belong according to MVC pattern?

  • 这只是解决问题的一种可能方法.例如,您可以将视图限制为单个观察者.
  • 您应该一直在想我可以更改 MVC 的任何一个部分,它仍然可以工作吗?"这让您考虑更改实施的任何一个部分可能对周围合同产生的可能问题.你应该明白每一层是如何实现的并不重要
  • 一个视图可以作为另一个子视图的控制器(或者作为一个子视图的另一个控制器的容器).这有时会吓到人们,但视图可以充当一个或多个子控制器/视图的父容器,这允许您开发复杂的 UI
  • 不要在合同中公开实现细节,例如,模型不应抛出 SQLException,因为另一个实现可能不是基于基于 SQL 的解决方案.不要暴露 UI 元素,这意味着所有实现都需要实现这些元素.如果我想要一个向用户呈现 JComboBox 而不是 JTextField 的视图的实现,会发生什么?这也是我不在视图契约中使用 ActionListener 的原因,因为我不知道 textWasChanged 事件实际上是如何由视图的实现生成的
  • This is just ONE possible way to approach the problem. For example, you could limit the view to a single observer.
  • You should always be thinking "can I change any one part of the MVC and will it still work?" This makes you think about the possible issues that changing any one part of the implementation might have on the surrounding contracts. You should get to the point that it simply doesn't matter how each layer is implemented
  • A view may act as a controller for another sub-view (or act as a container for another controller of a sub-view). This can scare people sometimes, but it's possible for a view to act as parent container for one or more sub controllers/views, this allows you to develop complex UIs
  • Don't expose implementation details in your contracts, for example, the model shouldn't throw a SQLException, as another implementation might not be based on a SQL based solution. Don't expose UI elements, this means that ALL implementations would then need to implement those elements. What happens if I want a implementation of the view that presents a JComboBox to the user instead of 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

这篇关于MVC 如何与 java swing GUI 配合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆