提问者:小点点

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


首先,我来自一个MVC的PHP背景,当我开始PHP的时候,我浏览了很多次,尽我所能完善我在PHP的MVC设计。很多人喜欢回答这个问题,这对我帮助很大。

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

在PHP中,我使用了服务、数据映射器和领域对象,从这个对我PHP有很大帮助的惊人答案中提出:模型应该如何在MVC中构建?

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

我有ControlllerContainer它创建所有控制器:

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回答,我如何使用他的想法

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

也许我误解了,所有的事情都应该在不同的语言中以不同的方式完成?但是我认为模式应该总是以相同的方式实现。

如果您需要更多信息,请告诉我。


共2个答案

匿名用户

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

1.经典MVC

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

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

视图-负责用户交互界面,UI元素布局,还监听模型更新,并在需要时更新图形界面。对模型有一些了解,例如下面所示,它知道如何处理“项目”列表。

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

2.MVP(模型视图演示器)

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

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

匿名用户

也许我是误解,所有的事情都应该用不同的语言来做?

没有误解;这种模式只是应用不同。

正如@ordous的评论和@udalmik的这个回答所指出的,Swing应用程序可能有多个MVC模式的实现。正如这里和这里所指出的,“不是每个交互都需要通过应用程序的控制器。”相比之下,Web应用程序很可能“在视图和控制器之间具有1:1的关系”。

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

几乎使用了链接中的答案,但事实上他的控制器扩展JPanel毁了它,完全让我困惑。

这可能会令人困惑,因为一个简单的Swing程序可能根本没有显式控制器。正如本大纲中建议的那样,控制器可以直接访问任何相关的视图和模型;它也可以监听用户与视图的交互。该示例旨在说明最简单的此类交互。用户与视图组件的交互唤起效果只是巧合。例如,这里引用的模拟具有更新应用程序视图和模型的视图组件的ControlPanelDisplayPanel直接监听需要模型更新的ComponentEvent。等等。

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

@Marco13对此进行了详细阐述,并在相关回答中引用了其他例子。