Swing と Windows Form と SWT
太一
2008/11/21
たいち(id:taichitaichi)について
- プログラマ
- eclipse pluginとjavascriptに時間を使ってる感じ
- いたづら大好き(id:warufuzaketaichi)
- 今は、カルドセプト(4511-3526-0665)。
- みんなカルドセプトを買うべき。
本日のテクノロジ
- Swing
- .NETにおけるWindowsForm
- The Standard Widget Toolkit(SWT)
比較項目
何か気付いたら、70人とか応募が来ちゃってて、どうしようかなーと。
直感的に理解し易い話と、分り辛いけど、必要な話を用意しました。
- UIデザイナ
- UIスレッドとワーカースレッドのディスパッチ
- 以下ボツネタ。
UIデザイナの話 (1)
まずは、使用するツール
- NetBeans 6.5 RC2(Swing)
- Microsoft Visual C# 2008 Express Edition (WindowsForm)
- eclipse 3.4.1 (SWT)
UIデザイナの話 NetBeans (1)
NetBeansの全景
UIデザイナの話 NetBeans (2)
コンポーネントレイアウト部分
UIデザイナの話 NetBeans (3)
プロパティ部分
UIデザイナの話 VisualStudio (1)
VisualStudioの全景
UIデザイナの話 VisualStudio (2)
コンポーネントレイアウト部分
UIデザイナの話 VisualStudio (3)
プロパティ部分
UIデザイナの話 Eclipse (1)
Eclipseの全景
UIデザイナの話 Eclipse (2)
コンポーネントレイアウト部分
UIデザイナの話 Eclipse (3)
プロパティ部分
UIデザイナの話 まとめ
- NetBeansとVisualStudioにUIデザイナの機能面で、殆ど差は見られない
- 但し、NetBeansで画面数が増えた時の挙動は、検証していないので要注意
- 明らかにeclipseのVisualEditorが一人負け
- 配布の仕組みである、JavaWebStartもチェックしてね
UIスレッドとワーカースレッドのディスパッチ
スタート、ストップ、その他の3つのボタン及び、
プログレスバーのあるUIを実装する事で、
プログラミングモデルの違いを明らかにします。
まずは、それぞれが完成した状態のUI
Swingの場合 (1)
Swing版を実装するに当って、
Swing Application Framework(SAF)を使用しています。
SAFでは、@Actionを使ってメソッドを
ApplicationContextのActionMapに登録し、
それをコンポーネント作成時に取り出して、
AbstractButton#setActionに引き渡す事で、
イベントと紐付ける事が出来ます。
イベントを処理するメソッドでは、
SwingWorkerを継承したTaskオブジェクトを返す事で、
処理内容を非同期化する事が可能になります。
この説明は、正直眠い!
Swingの場合 (2)
という訳でコードの抜粋
ActionMap actionMap = Application.getInstance(
desktopapplication1.DesktopApplication1.class)
.getContext()
.getActionMap(DesktopApplication1View.class, this);
jButton1.setAction(actionMap.get("startProgress"));
〜〜〜
@Action(block = Task.BlockingScope.ACTION)
public Task startProgress() {
switchButton(false);
this.progressTask = new StartProgressTask(getApplication());
return this.progressTask;
}
Swingの場合 (3)
Taskの中
private class StartProgressTask extends
org.jdesktop.application.Task
Swingの場合 (4)
まとめて全部
WindowsFormの場合 (1)
WindowsFormでは、BackgroundWorkerと言うAPIを使います。
このAPIを使うのは非常に簡単で、
以下の3つのイベントを実装するだけです。
- DoWork
- バックグラウンドで処理を実装する。
この中で、キャンセルのチェックや進捗イベントのトリガを行う。
- ProgressChanged
- 進捗の変化に伴ってトリガされるイベント。
このイベントはUIスレッド上で実行される。
- RunWorkerCompleted
- 処理が完了すると共にトリガされるイベント。
このイベントはUIスレッド上で実行される。
WindowsFormの場合 (2)
DoWorkイベントの抜粋
private void backgroundWorker1_DoWork
(object sender, DoWorkEventArgs e) {
BackgroundWorker bw = sender as BackgroundWorker;
for (int i = 0; i < 100; i++) {
if (e.Cancel = bw.CancellationPending) {
return;
} else {
Thread.Sleep(100);
bw.ReportProgress(1);
}
}
}
WindowsFormの場合 (3)
ProgressChanged、RunWorkerCompletedイベントの抜粋
private void backgroundWorker1_ProgressChanged
(object sender, ProgressChangedEventArgs e) {
progressBar1.Increment(e.ProgressPercentage);
}
private void backgroundWorker1_RunWorkerCompleted
(object sender, RunWorkerCompletedEventArgs e) {
if (e.Cancelled == false) {
MessageBox.Show(this,"Finished");
}
this.progressBar1.Value = 0;
switchButton(true);
}
WindowsFormの場合 (4)
partial classを除くユーザコード
WindowsFormの場合 (5)
VisualStudioが生成するpartialコード
SWTの場合 (1)
SWTでは、Rich Client Platform(RCP)上にUIを構築します。
RCPは、SWTによるスタンドアロンアプリケーションを実装する為の環境です。
RCPでは、Jobと言うクラスを使ってバックグラウンド処理を実現します。
Jobでは、そのサブクラス毎に実装するメソッドが違うのですが、
今回はrunメソッドを実装します。
SWTの場合 (2)
Jobの実装とその実行
Job job = new Job("heavy work") { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
for (int i = 0; i < 100; i++) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
} else {
Thread.sleep(100);
monitor.worked(1);
}
}
} catch (InterruptedException e) {
return Status.CANCEL_STATUS;
} finally {
monitor.done();
}
return Status.OK_STATUS;
}
};
job.schedule();
SWTの場合 (3)
まとめて全部
UIスレッドとワーカースレッドのディスパッチ まとめ
- Swingでは、SAFを使うとそこそこ簡単にバックグラウンド処理が書ける。
但し、文字列リテラルを濫用する事になるので、落とし穴はある。
javax.swing.SwingUtilities#invokeLaterは、もういらないかもね。
- WindowsFromでは、BackgroundWorkerを使う。これは、劇的に簡単。
- SWTでは、Jobを使う。これは、前提条件がそれなりにあるが簡単。
まとめ
- Swingは、野暮ったい見た目さえ気にしなければ、出来る子
- WindowsFormは、実行環境がWindowsなら、最高に出来る子
- SWTは、eclipse platform上で動作させるなら、結構出来る子
但し前提となる知識が膨大にあるので、挫けない心と、
レイアウト時には、フォースの様な何か感じる力が必要。
ご清聴ありがとうございました。
色々と至らない部分があるかと思いますが、
何はともあれ、最後までお聞き頂きありがとうございました。