MVC - Java Swing中的Observer / Observable模式

时间:2012-09-08 16:09:30

标签: java swing model-view-controller observer-pattern

我正在尝试构建一个基于MVC的Swing用户界面,并且对该主题有几个问题。提出问题的最佳方式是借助一个简单的例子。

假设我们有一个带有一个JButton和3个JTextField的JDialog。当按下该按钮时,我想要关闭另一个JDialog,并打开另一个需要来自3个JTextFields的数据。

这样做的简单方法(只需要代码片段,不需要惹恼你):

myButton.addMouseListener(new MouseAdapter(){

    @Override
    public void mouseClicked(MouseEvent evt){
        firstFrame.setVisible(false);
        secondFrame.setData(jTextField1.getText(),jTextField2.getText(),jTextField3.getText());//just sending the data to the new window, would be this or something similar
        secondFrame.setVisible(true);
        }});

或类似的东西。

第一个问题:如果我不使用匿名内部类但决定为我的Listener使用单独的类,我如何将数据从3个JTextField传递给我的mouseListener类?除了在Listener类中保留视图的引用之外,还有其他选择吗?

继续,给出MVC模式:

第二个问题:我认为听众(根据MVC的控制器)在没有模型参与的情况下调用另一个窗口是有道理的,我认为这是工作。但是需要从一个窗口传递到下一个窗口的数据(来自3JTextFields的数据)不应该通过模型吗?就像让第一个窗口在模型中保存数据一样,然后当第二个窗口需要它们时,从模型中请求它们。

第三个问题:我正在考虑使用Observer / Observable模式。如何在此示例中使用它来打开最后一个窗口?我的意思是因为(我认为)Controller是打开第二个窗口的类,这意味着必须观察监听器,第二个窗口必须是Observer,以便监听器会说

 notifyObservers("openSecondWindow");

然后第二个窗口会看到并自行打开?

最后:我听说PropertyChangeListener也可以正常工作,并且它有时会优先于Observer / Observable Pattern。你对此有何看法,特别是关于我的例子。

我很困惑..

感谢您的时间。

2 个答案:

答案 0 :(得分:0)

我不确定Java的具体方面。但谈到OOP,通过事件驱动设计使应用程序分离是非常合理的。因此,您不是直接处理组件,而是触发事件,如您所写:notifyObservers("openSecondWindow");

但是,您不需要通过模型层来执行此操作。相反,您应该有一个代表给定事件的event类,并在事件类中设置所提及字段的值。

类似的东西:

exampleEvent.setProperty1('blah').setProperty2('blah2');
notify('openSecondFrame', exampleEvent);

我刚刚发布了一个有关此事件驱动内容的问题:

PHP: Am I mixing up event-driven programming with signals-aware interfaces (Signal and Slots / Observer Pattern)?

您可能有兴趣阅读几个链接(它是PHP,但这个概念适用于OOP)。

因此,遵循这一概念,最好创建一个EventHandler组件来管理这些事件和信号。

但是再次考虑到我并不精通Java。这只是关于OOP。

答案 1 :(得分:0)

第一个问题

  

如果我不使用匿名内部类但决定为我的Listener使用单独的类,我将如何将数据从3个JTextField传递给我的mouseListener类?

您单独的MouseAdapter课程会有一个构造函数,您可以将JPanel课程中的内容传递给MouseAdapter课程。

此代码适用于ActionListener,但我认为总体思路将向您展示如何编写MouseAdapter类。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import com.ggl.project.planner.model.Planner;
import com.ggl.project.planner.model.Project;
import com.ggl.project.planner.view.CreateUpdateProjectDialog;
import com.ggl.project.planner.view.ProjectPlannerFrame;

public class CreateProjectActionListener implements ActionListener {

    protected Planner planner;

    protected Project project;

    protected ProjectPlannerFrame frame;

    public CreateProjectActionListener(ProjectPlannerFrame frame,
            Planner planner, Project project) {
        this.frame = frame;
        this.planner = planner;
        this.project = project;
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        CreateUpdateProjectDialog dialog = 
                new CreateUpdateProjectDialog(frame, project, true);
        if (dialog.isOkPressed()) {
            planner.setProjectOpen(true);
        }
    }

}

第二个问题

  

我认为听众(根据MVC的控制器)在没有模型参与的情况下调用另一个窗口是有道理的,我认为这是我的工作。但是需要从一个窗口传递到下一个窗口的数据(来自3JTextFields的数据)不应该通过模型吗?就像让第一个窗口在模型中保存数据一样,然后当第二个窗口需要它们时,从模型中请求它们。

我不确定我理解你的问题。当我构建GUI时,我有一个或多个数据模型来表示GUI中的值。这些数据模型的实例将通过构成GUI的大多数组件传递。

应用程序的其余部分通过模型访问GUI信息。

在我作为第一个问题答案的一部分发布的ActionListener课程中,有2个数据模型,ProjectPlannerProject特定于特定项目,而Planner是GUI的全局项目。

第三个问题

  

我正在考虑使用Observer / Observable模式。如何在此示例中使用它来打开最后一个窗口?

Swing已经内置了侦听器模式。您可以将动作侦听器用于自己的操作。您甚至可以将自己的侦听器类型添加到Swing中,尽管这是一个痛苦的过程。当我将JPanel扩展为JCroppingPanel时,我添加了自己的侦听器类型。