2009-05-20 12 views
4

Java SwingでMVCアーキテクチャのアプリケーションを使っています。プログレスバーを追加したいのですが、JProgressBarを私のビューに組み込むGood Design Methodsについて混乱しています。私は必要があります。プログレスバー+ JavaのMVC =?

  • は私のコントローラの状態にDefaultBoundedRangeModelを追加し、それをエクスポートしますか?私のモデルの状態にJProgressBarの者の視覚的な状態を接続しようとするバインディング

    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?

    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でアプリケーションのための現実的なソースの良い例に私を指すことができますか?

答えて

3

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

いいえ(〜1):まず、DefaultBoundedRangeModelはjavax.swingクラスです。私の意見では、これらのクラスはモデルに配置されていません。例えば、RMIを介してアクセスされているサーバー上のモデルを考える - 突然javax.swingクラスを置くと、 "正しくない"ように見えます。 しかし、本当の問題は、あなたのモデル(有界モデル)の一部を他の人に与えていることです。発生したイベントやクエリを制御することはできません。

いいえ(〜2):いいえ。バインディングは楽しいですが、少なくとも私の意見では、データモデルとUIモデルの間ではなく、UIモデルとUIコンポーネントを同期させる必要があります。ここでも、データモデルがRMIによってアクセスされるリモートサーバーに存在する場合にはどうなるか考えてください。

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

これが役に立ちます。我々のアプリ(MVC、約100 KLOC)では

+0

、あなたはSwingWorkerのを見なければならない - それは、この問題を扱う(からの進捗状況を更新バックグラウンドタスク)。 –

3

私は他の何かを言うでしょう。

私がMVCで持っていた問題は、モデルの抽象度を定義することです。

  • モデルは

  • モデルは、プログラムそれ自身のためのオブジェクトのいくつかの他の種の可能性がUIコンポーネントのオブジェクトのいくつかの並べ替えである可能性があります。

  • モデルは、ビジネスモデルとしての高い可能性があります。

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

articleは、スイングアーキテクチャを記述し、モデルの使用方法を明らかにする可能性があります。

3

我々はそれがそのように持っている(パターンオブザーバー、実際に):ところで

/** 
* 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()); 
    } 
    ... 
}