5

所以我在 Java Swing 中有一个漂亮的、漂亮的 MVC 架构应用程序,现在我想添加一个进度条,我对将 JProgressBar 合并到我的视图中的良好设计方法感到困惑。我是不是该:

  • 将 DefaultBoundedRangeModel 添加到我的控制器状态,然后导出它?

    class Model {
      final private DefaultBoundedRangeModel progress
        = new DefaultBoundedRangeModel();
    
      public void getProgressModel() { return progress; }
      public void setProgressCount(int i) { progress.setValue(i); }
    }
    
    class Controller {
      Model model;
      int progressCount;
      void doSomething()
      {
         model.setProgressCount(++progressCount);
      }
    }
    
    class View {
      void setup(Model m)
      {
        JProgressBar progressBar = /* get or create progress bar */  ;
        progressBar.setModel(m.getProgressModel());
      }
    }
    
    /* dilemma: Model allows progress to be exported so technically
     all of the progress state could be set by someone else; should it be put
     into a read-only wrapper? */
    
  • 使用 JGoodies Binding 尝试将 JProgressBar 的视觉状态连接到我的模型的状态?

    class Model {
      private int progress;
    
      public void getProgressCount() { return progress; }
      public void setProgressCount(int i) { progress = i; }
    }
    
    class View {
      void setup(Model m)
      {
        ProgressBar progressBar = /* get or create progress bar */  ;
        CallSomeMagicMethodToConnect(m, "progressCount", progressBar, "value");
        // is there something that works like the above?
        // how do I get it to automatically update???
      }
    }
    
  • 或者是其他东西???

编辑:更具体地说:有人可以为我指出一个Java应用程序的现实来源的好例子,它有一个包含进度条的状态栏,并且有一个体面的MVC实现吗?

4

3 回答 3

3

我想说,别的。

我在 MVC 中遇到的问题是定义模型的抽象级别。

  • 模型可以是 UI 组件的某种对象

  • 模型也可以是它自身的程序的某种其他类型的对象。

  • 模型可以和商业模型一样高。

在这种情况下,我将为进度条分离模型/组件对,并在单独的控制器类中处理它们。

本文描述了 Swing 架构,并可能阐明它在内部使用模型的方式。

于 2009-05-20T19:05:56.980 回答
3

否(对 1)和 NOOOO(对 2)。至少在我看来。

否(对 1):首先,DefaultBoundedRangeModel 是一个 javax.swing 类。在我看来,这些类在模型中没有位置。例如,考虑生活在服务器上的模型,通过 RMI 访问 - 突然在那里放置一个 javax.swing 类似乎“不正确”。但是,真正的问题是您将模型的一部分(有界模型)提供给其他人,而无法控制触发的事件或进行的查询。

否(对 2):呃。绑定很有趣,但(至少在我看来)应该用于 UI 模型和 UI 组件之间的同步,而不是数据模型和 UI 模型之间的同步。同样,想想如果您的数据模型位于远程服务器上,由 RMI 访问会发生什么。

所以呢?好吧,这只是一个建议,但我会添加一个事件侦听器接口并添加标准事件侦听器订阅方法(addListner(...)、removeListener(...))。当我有更新时,我会在我的模型中调用这些监听器。当然,我会确保记录调用线程(或者说它无法确定),以便客户端(本例中的 UI)能够正确同步(invokeLater 和朋友)。由于监听器服务将被控制器公开,这将允许模型存在于任何地方(甚至允许监听器被远程调用或池化)。此外,这会将模型与 UI 分离,从而可以构建更多包含它的模型(翻译器/装饰器/依赖模型)。

希望这可以帮助。

于 2009-05-20T20:24:44.027 回答
3

在我们的应用程序(MVC,大约 100 KLOC)中,我们有它(实际上是模式观察者):

/**
 * Observer on progress changes
 */
public interface IProgressListener {
  public void setProgress(ProgressEvent e);
}

public class ProgressEvent extends ... {
  private int progressCount;
  // setter + getter
  ...
}

class Model {
  public void addProgressListener(IProgressListener l);
  protected void fireProgressChange(ProgressEvent e);   // call .setProgress() on listeners
}

class Controller {
  private Model model;
}

class View extends ProgressBar implements IProgressListener {
  ...
  // IProgressListener implementation
  public void setProgress(ProgressEvent e) {
    this.setValue(e.getProgress());
  }
  ...
}
于 2009-05-25T12:26:57.577 回答