使用Java中的Swing在GUI开发中正确实现MVC模式

时间:2014-08-26 09:36:55

标签: java swing user-interface model-view-controller

首先,我来自MVC的大背景,当我开始使用PHP时,我浏览了很多次,尽我所能并完善我在PHP中的MVC-Like设计。很多人都喜欢回答了很多帮助我的答案。

但是在Swing中开始GUI开发之后,关于Swing中MVC的答案是完全不同的。例如,模型也是一种观点?根据{{​​3}} TextElementModel这里没有任何逻辑业务,它所做的只是标记(设置颜色等)和设置数据,如设置文本等。当我用PHP开发时,没有AbstractModel这样的东西,因为我总是被告知模型不是一个类,或者更多,它是处理逻辑业务的整个层。

在PHP中,我使用了服务,数据映射器和域对象,这个惊人的答案提示了我在PHP中帮助我很多:Oracle's Suggestions

我的尝试

再次阅读之后,我想在Java中做一个类似的事情:

我有ControllerContainer创建所有控制器:

public class ControllerContainer {

    private JFrame frame;

    public ControllerContainer(JFrame rune) {
        this.frame = frame;
    }

    public void initControllers() {
        Atest test = new Atest(frame);
        test.registerView("test", new ViewTest(test));
    }

}

如您所见,我将名为“test”的视图添加到控制器的实例ViewTest,现在它将在框架中可见,并且可以接受输入。

我的Controller课,应该是抽象的,但我还没有把它抽象化:

public class Controller {

    private JFrame frame;

    private Map<String, Component> views = new HashMap<String, Component>();

    public Controller(JFrame frame) {
        this.frame = frame;
    }

    protected void registerView(String title, Component c) {
        this.views.put(title, c);
        this.frame.add(c);
    }

    protected void deregisterView(String title) {
        this.frame.remove(this.views.get(title));
        this.views.remove(title);
    }

    protected Component getView(String title) {
        return this.views.get(title);
    }
}

测试控制器:

public class Atest extends Controller {

    public Atest(JFrame frame) {
        super(frame);
    }

    public void hit() {
        ((ViewTest) super.getView("test")).changeColorBlue();
    }
}

我的TestView

public class ViewTest extends JPanel {

    private final Atest controller;

    public ViewTest(Atest c) {
        this.controller = c;
        setBackground(Color.RED);
        setLocation(0,0);
        setSize(300, 300);
        setLayout(null);

        JButton b = new JButton("hello");
        b.setSize(150, 150);
        b.setLocation(0,0);

        b.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent arg0) {
                controller.hit();
            }
            @Override
            public void mouseEntered(MouseEvent arg0) {
            }
            @Override
            public void mouseExited(MouseEvent arg0) {
            }
            @Override
            public void mousePressed(MouseEvent arg0) {
            }
            @Override
            public void mouseReleased(MouseEvent arg0) {
            }
        });

        add(b);
    }

    public void changeColorBlue() {
        setBackground(Color.BLUE);
    }

}

问题

如您所见,我的视图会创建一个新按钮,并为其添加一个鼠标侦听器。监听器将有权访问控制器以传递输入。控制器获取输入并更改视图。

基本上,控制器立即被迫更新视图,没有任何严肃的逻辑业务,因为在我的情况下不需要它。

根据我上面发布的链接,tereško回答,我怎样才能使用他的想法&amp;有关Java Swing的建议是否正确?

在PHP背景之后,我真的很困惑。

也许我是误会,一切都应该以不同的语言完成?但我认为模式应该始终以相同的方式实现。

如果您需要更多信息,请与我们联系。

2 个答案:

答案 0 :(得分:17)

MVC 模式它是一种常见的范例,因此一般来说,语法编排语言之间没有区别。 然而,实现和一些术语有时看起来不同。在 Java Swing 中,通常会看到以下两种方法:

<强> 1。经典MVC

控制器 - 侦听用户界面操作,执行相应的模型更新。可以从不同的 视图中听取操作。

模型 - 表示状态和域逻辑,修改状态的方法。通知侦听器模型更新(多个视图可以监听更新)。 模型是独立的,对侦听器及其逻辑一无所知。

查看 - 负责用户界面,UI元素布局,还可以监听模型更新并在需要时更新图形界面。有一些关于模型的知识,在下面的例子中它知道如何处理“项目”列表。

设计一些简单的“待办事项”应用程序可能如下所示:

enter image description here

<强> 2。 MVP(模型视图演示者)

控制器查看模型之间充当中介查看变得非常薄,对模型一无所知,只与控制器进行交互。 控制器会同时监听查看模型并执行相应的操作。

enter image description here

Swing 本身增加了一些混乱,因为它使用MVC模式作为其UI组件。每个UI控件都有一个模型和视图。设计新的UI组件变得更加容易,但是在整个应用程序设计的“大图”中 - UI控件保留在视图层。

答案 1 :(得分:9)

  

也许我误会了,一切都应该以不同的语言完成?

没有误解; pattern仅适用于不同的方式。

如@ordous的comment和@udalmik的answer所述,Swing应用程序可能有多个MVC模式的实现。如上所述herehere,“不每个交互都需要通过应用程序的控制器。”相比之下,web application可能“在视图和控制器之间具有1:1的关系。”

Swing可分离模型architecture,引用here,“将每个组件的视图和控制器部分折叠成单个UI(用户界面)对象。” Swing控制器分散在JComponent的后代中,通常位于组件的UI delegate中。作为一个具体示例,BasicButtonUI包含处理用户鼠标交互的BasicButtonListener

  

几乎在链接中使用了answer,但是他的控制器扩展JPanel毁了它,这让我很困惑。

这可能令人困惑,因为简单的Swing程序可能根本没有明确的控制器。根据此outline的建议,控制器可以直接访问任何相关的视图模型;它还可以监听用户与视图的交互。 example旨在说明最简单的此类互动。仅仅巧合的是,用户与视图组件的交互引起了这种效果。例如,引用的模拟here具有ControlPanel个视图组件,用于更新应用程序的视图和模型。 DisplayPanel直接侦听需要模型更新的ComponentEvent。等等。

然后,您的应用程序控制器可以自由地专注于应用程序的需求。

@ Marco13详细阐述了这一点,并引用了此相关answer中的其他示例。