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???
      }
    }
    
  • または、他の何か???

編集:より具体的に: プログレス バーを含むステータス バーがあり、適切な MVC 実装がある Java のアプリケーションの現実的なソースの良い例を教えてもらえますか?

4

3 に答える 3

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 に答える
3

私は、何か他のものだと思います。

私が MVC で抱えていた問題は、モデルの抽象化のレベルを定義することです。

  • モデルはUIコンポーネントのある種のオブジェクトである可能性があります

  • モデルは、プログラム自体の他の種類のオブジェクトである可能性もあります。

  • モデルは、ビジネスモデルと同じくらい高くなる可能性があります。

この場合、プログレス バーのモデルとコンポーネントのペアを分離し、それらを別のコントローラー クラスで処理します。

この記事では、Swing アーキテクチャについて説明し、内部でモデルを使用する方法を明確にする可能性があります。

于 2009-05-20T19:05:56.980 に答える
3

いいえ (1 に) と NOOOO (2 に)。少なくとも私の意見では。

いいえ (1 まで): まず、DefaultBoundedRangeModel は javax.swing クラスです。私の意見では、これらのクラスはモデルには存在しません。たとえば、サーバー上に存在し、RMI 経由でアクセスされるモデルについて考えてみてください。突然そこに javax.swing クラスを配置すると、「正しくない」ように見えます。ただし、実際の問題は、モデルの一部 (制限されたモデル) を他の誰かに与えており、イベントの発生やクエリの実行を制御できないことです。

いいえ (to 2): うーん。バインドは楽しいものですが、(少なくとも私の意見では) データ モデルと UI モデルの間ではなく、UI モデルと UI コンポーネントの間の同期に使用する必要があります。繰り返しになりますが、データ モデルがリモート サーバー上にあり、RMI によってアクセスされるとどうなるかを考えてみてください。

だから何?これは単なる提案ですが、イベント リスナー インターフェイスを追加し、標準のイベント リスナー サブスクリプション メソッド (addListner(...)、removeListener(...)) を追加します。更新が行われているときに、モデル内からこれらのリスナーを呼び出します。もちろん、クライアント (この場合は UI) が正しく同期できるように (invokeLater と友人)、呼び出し元のスレッドを文書化する (または決定できないと言います) ようにします。リスナー サービスはコントローラーによって公開されるため、モデルをどこにでも置くことができます (リスナーをリモートで呼び出したり、プールしたりすることも可能です)。また、これによりモデルが UI から切り離され、それを含むモデル (トランスレーター / デコレーター / 依存モデル) をさらに構築できるようになります。

お役に立てれば。

于 2009-05-20T20:24:44.027 に答える