フレームワーク利用時のアプリケーションのライフサイクルは以下の流れで行われます。
- launch -- 起動時に、フレームワーク提供のこのメソッドを呼ぶ。
- initialize -- フレームワークからオーバーライドした本メソッドが呼ばれる。
- startup -- フレームワークからオーバーライドした本メソッドが呼ばれる。
- ready -- フレームワークからオーバーライドした本メソッドが呼ばれる。
- exit -- 終了時に、フレームワーク提供のこのメソッドを呼ぶ。
- shutdown -- フレームワークからオーバーライドした本メソッドが呼ばれる。
initialize・ready・shutdownはApplicationクラス内で空メソッドとして定義されており、必要時に実装します。最低限のアプリケーションではlaunch・startupを実装すれば済みます。
launchメソッドの呼び出しにより、initialize, startup, readyメソッドが順番に実行されることになります。
フレームワークを利用しない場合
フレームワークを利用しなかった場合の一般的なSwingアプリケーションの場合は以下の様になります。
public class BasicApp implements Runnable { JFrame mainFrame; JLabel label; public void run() { mainFrame = new JFrame("BasicApp"); label = new JLabel("Hello, world!"); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainFrame.add(label); mainFrame.pack(); mainFrame.setVisible(true); } public static void main(String[] args) { Runnable app = new BasicApp(); try { SwingUtilities.invokeAndWait(app); } catch (Exception e) { e.printStackTrace(); } } }
フレームワークを利用した場合
これは、フレームワークを利用すると、以下のように書けます。
public class BasicFrameworkApp extends Application { private JFrame mainFrame; private JLabel label; @Override protected void startup() { mainFrame = new JFrame("BasicFrameworkApp"); mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); label = new JLabel("Hello, world!"); mainFrame.add(label); mainFrame.pack(); mainFrame.setVisible(true); } public static void main(String[] args) { Application.launch(BasicFrameworkApp.class, args); } }
フレームワークではlaunch メソッド実行で、EDS(イベントディスパッチスレッド)上で、最初にinitialize メソッドが呼ばれます。initialize メソッドはApplication上で空実装となっているので必要に応じてオーバーライドして初期化処理が行えます。
その後abstractとして定義してあるstartupメソッドが呼ばれるので、オーバーライドしてUI構築等を行います。startupが終了すると、フレームワークはready メソッドを呼びます。
こちらもApplication上で空実装となっているので必要に応じてオーバーライドしてUI初期化後のタスクを実装します。
SingleFrameApplicationの利用
SingleFrameApplication を使用すると、上記ライフサイクルのほかにフレーム生成・リソースからのインジェクション・セッションの永続化などがサポートされます。
public class BasicSingleFrameApp extends SingleFrameApplication { JLabel label; @Override protected void startup() { getMainFrame().setTitle("BasicSingleFrameApp"); label = new JLabel("Hello, world!"); label.setFont(new Font("SansSerif", Font.PLAIN, 22)); show(label); } public static void main(String[] args) { Application.launch(BasicSingleFrameApp.class, args); } }
SingleFrameApplicationではなく、Applicationを直接継承したサブクラスを作成した場合、アプリケーション終了時にApplicationはexitメソッドを直接呼びません。
以下の実装とすることで、Application内のshutdown()が呼ばれます。
protected void startup() { mainFrame = new JFrame("BasicFrameworkApp"); mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); mainFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { mainframe.setVisible(false); exit(); } }); label = new JLabel("Hello, world!"); mainFrame.add(label); mainFrame.pack(); mainFrame.setVisible(true); }
SingleFrameApplication では、フレームに自動で対応付けられたWindowListener がexitを呼び、それによりshutdown()メソッドが呼ばれます。この時、SingleFrameApplicationのshutdownメソッド内で終了時のセッションの永続化等を実施しているので、オーバーライドする場合は以下のようにすることを忘れないで下さい。
@Override protected void shutdown() { super.shutdown(); // ・・ }
アプリケーション終了時の挙動
アプリケーションの終了時の挙動を制御するには、ExitListenerインターフェースの以下のメソッドを利用します。
- public boolean canExit(EventObject e)
- public void willExit(EventObject e)
以下の例では終了時に確認用のダイアログを表示する例です。
@Override protected void startup() { ・・・ addExitListener(new ExitListener() { public boolean canExit(EventObject e) { boolean bOkToExit = false; Component source = (Component) e.getSource(); bOkToExit = JOptionPane.showConfirmDialog(source, "Do you really want to exit?") == JOptionPane.YES_OPTION; return bOkToExit; } public void willExit(EventObject event) { } }); show(exitButton); }