MVC Java:控制器如何为视图的子类设置侦听器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20027887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:26:30  来源:igfitidea点击:

MVC Java: How does a Controller set listeners to the children classes of a View

javamodel-view-controllerobserver-pattern

提问by

I have a Controller, and a View with many children views with children with children. Example: JPanels within JPanels that have buttons and fields for a controller to pass to the model.

我有一个控制器,以及一个有很多孩子的视图,有孩子的孩子。示例:JPanels 中的 JPanel 具有用于控制器传递给模型的按钮和字段。

The current way I'm doing it is instantiating 'Controllers' in the view that have action listeners and access my models which are singletons. This works- But it's definitely not MVC.

我目前的做法是在具有动作侦听器并访问我的单例模型的视图中实例化“控制器”。这有效 - 但它绝对不是 MVC。

So the question is- how do I do it?

所以问题是 - 我该怎么做?

Is the only way to daisy chain from the controller: mainview.getSubView().getSubView().getSubView().setActionListener(new AL()); and: mainview.getSubView().getSubView().getSubView().getSomeTextFieldText();

是从控制器菊花链的唯一方法: mainview.getSubView().getSubView().getSubView().setActionListener(new AL()); 和: mainview.getSubView().getSubView().getSubView().getSomeTextFieldText();

This seems extremely impractical [and I can't see the benefits of this method]

这似乎非常不切实际 [而且我看不到这种方法的好处]

Any tips or guidance would be helpful. No tutorial I see explains MVC with children views.

任何提示或指导都会有所帮助。我看到没有教程用子视图解释 MVC。

On a side note- I know I should have the views and models use observable/observer - but even with those I have a problem with setting action listeners.

附带说明 - 我知道我应该让视图和模型使用 observable/observer - 但即使是那些我在设置动作侦听器方面也有问题。

采纳答案by Jason C

I think you are making a mistake of conceptually tying a "view" to individual GUI components. In the MVC model there really is not such concept as a "subview".

我认为您在概念上将“视图”绑定到单个 GUI 组件是错误的。在 MVC 模型中,确实没有“子视图”这样的概念。

If you have a frame, for example, with many panels and subpanels and subcomponents such as buttons, etc., that entire thingis the view/controller interface in MVC. Your top-level frame (or some encapsulating class, perhaps your GUI has many frames, it doesn't matter) would provide the interface to the controller (via, say, events) and the view (via, say, listeners). Exactly how your UI is arranged is abstracted behind that. Think of your entire UI as a black box. How events are dispatched / provided from the internal components is part of the UI implementation, and this may very well involve event chains and delegates and etc. -- but that is not something the view/controller is concerned with.

例如,如果您有一个具有许多面板和子面板以及子组件(例如按钮等)的框架,则整个内容就是 MVC 中的视图/控制器接口。您的顶级框架(或一些封装类,也许您的 GUI 有很多框架,这无关紧要)将提供到控制器(例如,通过事件)和视图(例如,通过侦听器)的接口。您的 UI 的确切排列方式是在其背后抽象出来的。把你的整个 UI 想象成一个黑盒子。如何从内部组件分派/提供事件是 UI 实现的一部分,这很可能涉及事件链和委托等——但这不是视图/控制器关心的问题。

So you end up with something like (conceptual example):

所以你最终会得到类似的东西(概念示例):

Model m = new Model();
View v = new View(m);
Controller c = new Controller(m);
MyFrame gui = new MyFrame(v, c);

Then:

然后:

public MyFrame (View v, Controller c) {

   // register listeners to view, e.g.
   v.addChangeListener(this /* or some other ui component */);

   // send events to controller, e.g.
   addActionListener(c /* or some interface that c provides */).

   // or even:
   deleteButton.addActionListener(new ActionListener(){
       @Override public void actionPerformed (ActionEvent e) {
           c.doDelete();
       }
   });   

}

In an ideal situation, you can completely rework the hierarchy of your GUI, having a totally different component tree and organization, and, providing the informationbeing conveyed through the GUI remains unchanged, the view and controller remain unchanged as well.

在理想情况下,您可以完全重新设计 GUI 的层次结构,拥有完全不同的组件树和组织,并且,如果通过 GUI 传达的信息保持不变,视图和控制器也保持不变。

Once you get used to the MVC pattern, you may start to take shortcuts here and there (for example, in many cases the view and/or controller are just middle-men for events, and the GUI itself sometimes ends up encapsulating the entire controller and view concepts, leaving you with a GUI, a model, and a bunch of event listeners -- the Swing event architecture is fairly MVC in itself), and boundaries may get fuzzier. That's OK. But there's no reason that either the view or the controller have to know about the structure and object tree in the GUI -- even in cases where controller/view are just abstract concepts instead of concrete classes.

一旦习惯了 MVC 模式,您可能会开始到处走捷径(例如,在许多情况下,视图和/或控制器只是事件的中间人,而 GUI 本身有时最终会封装整个控制器和视图概念,给您留下一个 GUI、一个模型和一堆事件侦听器——Swing 事件体系结构本身就是 MVC),并且边界可能会变得更加模糊。没关系。但是没有理由让视图或控制器必须知道 GUI 中的结构和对象树——即使在控制器/视图只是抽象概念而不是具体类的情况下。

Sometimes MVC can get especially fuzzy when working with Swing because you kind of end up doing everything in an MVC way naturally, so when you try to explicitly impose an MVC pattern on your architecture, you're left wondering why that doesn't seem to change much at all (and it becomes difficult to see the benefits, because you forget that you're already doing it). Sometimes it's more of a way of thinkingthan a concrete way of doing.

有时 MVC 在使用 Swing 时会变得特别模糊,因为您最终会很自然地以 MVC 方式做所有事情,所以当您尝试将 MVC 模式显式强加到您的架构时,您会想知道为什么这似乎没有根本没有改变(并且很难看到好处,因为你忘记了你已经在做)。有时它更像是一种思维方式,而不是一种具体的做事方式

Essentially, anytime your model is completely independent of your GUI, you are using some incarnation of MVC.

本质上,任何时候您的模型完全独立于您的 GUI,您都在使用 MVC 的一些化身。

Edit: I noticed you also tagged this with "observer pattern" and mentioned it briefly. It's worth noting that many times, explicitly implementing an observer pattern for Swing-based GUIs, at least in relatively simple applications, adds nothing but a redundant abstraction layer, as the entire Swing API is already fundamentally based on this design pattern (it's the whole event -> listener subsystem).

编辑:我注意到你还用“观察者模式”标记了它并简要提到了它。值得注意的是,很多时候,为基于 Swing 的 GUI 显式实现观察者模式,至少在相对简单的应用程序中,只添加了一个冗余的抽象层,因为整个 Swing API 已经从根本上基于这种设计模式(这是整个事件 -> 侦听器子系统)。

Frequently I have found that something like the following works well, using the so-called observer pattern all around, where the controller was essentially just a collection of event listeners, like:

我经常发现像下面这样的东西很有效,使用所谓的观察者模式,其中控制器本质上只是一个事件侦听器的集合,例如:

 public class Controller {
     Model m;
     public ActionListener getDeleteListener () {
         return new ActionListener() {
             @Override public void actionPerformed (ActionEvent e) {
                 m.deleteSomething();
             }
         };
     }
 }

And then the GUI does something like:

然后 GUI 会执行以下操作:

 public class GUI extends JFrame {
     JButton deleteButton; 
     public GUI (View v, Controller c) {
         deleteButton.addActionListener(c.getDeleteListener()); 
     }
 }

But, there are many ways to skin that cat. In that example, even, once you are familiar with the concept, and if it is appropriate, you could take a shortcut and just have the GUI constructor register listeners that modify the model. Then, as mentioned above, the controller becomes just an abstract concept.

但是,有很多方法可以给那只猫剥皮。在那个例子中,即使你熟悉了这个概念,如果合适的话,你可以走捷径,让 GUI 构造函数注册修改模型的监听器。那么,如上所述,控制器就变成了一个抽象的概念。