2011-12-21 18 views
3

SWTシェルを処分する適切な方法は何ですか? Dialog APIのドキュメントにあるテンプレートに従って、いくつかのダイアログを作成しました。 SWT API for Dialog saysSWTシェル(およびダイアログ)を破棄する方法は?

ユーザー定義のダイアログは、一般的にこのような何か に見えるための基本的なテンプレート:私はを作成したダイアログがは、Windows上で自分のタスクバーのアイコンを持っていない

public class MyDialog extends Dialog { 
     Object result; 

     public MyDialog (Shell parent, int style) { 
       super (parent, style); 
     } 
     public MyDialog (Shell parent) { 
       this (parent, 0); // your default style bits go here (not the Shell's style bits) 
     } 
     public Object open() { 
       Shell parent = getParent(); 
       Shell shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); 
       shell.setText(getText()); 
       // Your code goes here (widget creation, set result, etc). 
       shell.open(); 
       Display display = parent.getDisplay(); 
       while (!shell.isDisposed()) { 
         if (!display.readAndDispatch()) display.sleep(); 
       } 
       return result; 
     } 
} 

を私はDialogを期待しています。私は今、正しく理解すれば、はWindows上で自分のタスクバーのエントリを受け取るでしょういくつかのシェルを作成したいですか?

上記のAPIドキュメントの指示とは対照的に、私はan articleも見てきました。これは、APIドキュメントに示されているようにwhileループを持つことが間違っていることを示唆しているようです。この資料では、代わりに、閉じるイベントリスナーを使用してシェルを廃棄することを提案しています。

SWTシェルを処分する正しい方法は何ですか(話題にあった間、ダイアログも同様)。

答えて

10

私はここで何が起こっているのかを説明してくれることを願っています。

Dialogは、基本的にサブクラス化するのに便利なクラスです。Shell自体はサブクラス化されていないためです。必要に応じて、Dialogを使わずにシェルを作成することもできます。この場合、MyDialogクラスは、他の人が同じ種類のダイアログを繰り返し開くために使用できるクラスです。

コードのこの作品は、(シェル上の閉じるボタンをクリックすると、デフォルトでシェルを配置する)限り、シェルが開いているとSWTのイベントループを駆動する:

  while (!shell.isDisposed()) { 
        if (!display.readAndDispatch()) display.sleep(); 
      } 

あなたは維持するために定期的にDisplay.readAndDispatchを呼び出す必要がありますあなたのSWTアプリケーションは「ロックアップ」しています。基本的には、オペレーティングシステムからのすべての着信イベント(キーボードとマウスイベント、再描画イベントなど)がアプリケーションによって正しく処理されます。 readAndDispatchは基本的にアプリケーションのイベントキューからイベントを受け取り、正しいリスナを呼び出します。 Eclipse RCPアプリケーションでは、通常、ワークベンチはイベント・ループを「ポンピング」する責任があります。 「手動」は、この文脈において、イベントループポンプのHere's a little more info about the event loop.

目的は、シェルが配置されていないながら戻ることMyDialog.openを防ぐが、それでも「ハング」からアプリケーションを保つことです。 MyDialog.openメソッドがシェルの廃棄を待つが、イベントループをポンピングしなかった場合、アプリケーションはイベントループが実行されていなければシェルに通知されることはない処分されるべきです!

お客様このパターンを使用せずにシェルを作成してください。

public class Shells { 
    private static int numDisposals = 0; 

    public static void main(String[] args) { 
     Display d = Display.getDefault(); 

     for (int i = 0; i < 5; i++) { 
      Shell s = new Shell(d); 
      s.open(); 
      s.addDisposeListener(new DisposeListener() { 
       @Override 
       public void widgetDisposed(DisposeEvent arg0) { 
        numDisposals++; 
       } 
      }); 
     } 

     while (numDisposals < 5) { 
      while (!d.readAndDispatch()) { 
       d.sleep(); 
      } 
     } 
    } 
} 
:ここですべてを一度シェルのトンを開き、非常に単純なSWTアプリケーションの例だと限りそれらの少なくとも1つがまだ開いているとして稼働し続け(私はパッケージ宣言や輸入を省略しました)

各シェルにDisposeListenerを追加するので、シェルを閉じたときに何らかのアクションを取ることができます。IShellListenerを使用して、closeイベントをより直接聞くこともできますし、実際にはそれを防ぐことさえできます(シェルに保存されていない作業がある場合など)。ここでは5つのシェルを起動する最初のプログラムに迷惑修正だとランダムにそれらを閉じてからあなたを防ぐ:

public class Shells { 
    private static Random r = new Random(); 
    private static int numDisposals = 0; 

    public static void main(String[] args) { 
     Display d = Display.getDefault(); 

     for (int i = 0; i < 5; i++) { 
      Shell s = new Shell(d); 
      s.open(); 
      s.addShellListener(new ShellAdapter() { 
       @Override 
       public void shellClosed(ShellEvent e) { 
        boolean close = r.nextBoolean(); 
        if (close) { 
         System.out.println("Alright, shell closing."); 
        } else { 
         System.out.println("Try again."); 
        } 
        e.doit = close; 
       } 
      }); 
      s.addDisposeListener(new DisposeListener() { 
       @Override 
       public void widgetDisposed(DisposeEvent arg0) { 
        numDisposals++; 
       } 
      }); 
     } 

     while (numDisposals < 5) { 
      while (!d.readAndDispatch()) { 
       d.sleep(); 
      } 
     } 
    } 
} 

がうまくいけば、これは物事をより明確に貢献してきました!


追加する編集:私はあなたのシェルのためのWindowsのタスクバーの項目を取得されない理由は全くわからないんだけど、私はそれはあなたがシェルの内を通過しているスタイルフラグとは何かを持っている疑いがありますコンストラクタ。私の例のシェルにはスタイルフラグはなく、すべてタスクバーのアイコンが表示されます。

+0

この非常に有益な回答ありがとうございます。タスクバーアイコンについて:私はダイアログウィンドウの親として「メインウィンドウ」を設定しました。新しいシェルのコンストラクタの親として別のシェルを渡すと、新しいシェルはタスクバーアイコンを受け取らず、新しいシェルは常にその親の上に(無視されないように)置かれます。親として表示されているシェルのみがタスクバーに表示されます(Windows 7)。少なくとも、これは私のテストが提案したものです。 – Buttons840

関連する問題