Applicationは何をやっているのか

 "XAMLとは"ではXAML文の中身については説明して、XAML文は結局のところWindowというクラスを定義をしていることを 説明したわけですが、実際のIronPythonのスクリプトファイル内ではWindowのオブジェクトをApplicationのRunメゾットに渡しています。
 では当然Applicationは何をやっているんだろうと疑問がでてくると思うので、今回はそのあたりを説明したいと思います。

 アプリケーションの管理

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'with_xaml.xaml')
  
  def Button_Click(self, sender, e):
    self.label1.Content = "ようこそ Iron Python Worldへ"

if __name__ == '__main__':
Application().Run(MyWindow())

 上記のスクリプトファイルではMyWindowクラスを定義した後、Application.Runメゾットを実行しています。 実際、"Application().Run(MyWindow())"の動作内容は次のとおりです。

1) Application()でApplicationのインスタンスが作成されます。
2) Application.Runメゾットが呼び出されます。
3) Application.Startupイベントが発生します。
4) Runメゾットに渡している引数"MyWindow()"によりMyWindowのインスタンスが作成されます。
5) MyWindowオブジェクトを表示します。
6) Application.Showdownメゾットが呼び出されます
7) Application.Exitイベントが発生します。
8) Application.Runメゾットが完了します。

以上がすべてですが、もう少し補足します。
結局Application.Run()って何をやっているのか?
 同じような問いかけがを3回になり、もうそろそろ嫌になってきているかも知れませんが、最後です。 Applicationオブジェクトの仕事は、詰まるところ"アプリケーションの管理"です。そしてApplication.Runメゾットによって "WindowsOSとの対話"が開始されます。
 "WindowsOSとの対話"とはGraphical User Interface(GUI)の真骨頂です。Iron Python入門のほとんどのスクリプトは コマンドラインというインターフェースでした。コマンドラインではユーザーからの反応は文字を入力してEnterキーを押すという ものしかありませんでした。しかし現在のパソコンではGUIというインターフェースで操作しています。例えば "キー入力する"、"マウスをクリックする"、"ドラッグする"などユーザーの反応は様々です。 そういったユーザーの反応についての対応をIron Pythonが全てやっているかというと、そんなことはありません。実際にやっているのは WindowsOSです。
 Iron PythonとWindowsOSとの対話が始まると、WindowsOSはユーザーがマウスをクリックしたりする反応に対して IronPythonに必要なものをWindowsメッセージとして送ります。ApplicationはWindowsメッセージ集として集めておいて、このWindowsメッ セージ集を定期的に見に行って、そのメッセージに合わせて随時スクリプトを実行していくというのが、GUIの仕組みです。
 実際Application.Runメゾットが実行されると、Windowsからメッセージを受け取る専門のDispatcherオブジェクトが作られて、 DispatcherのRunメゾットが実行されます。

 Application.Runが実行されるタイミングで、別の動作も付随して行わせたい場合には、その記述をStartupイベントに記述します。 例えば、次のようにします。

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox
import wpf
from System.Windows import Application, Window
class MyApp(Application):
  def __init__(self):
    self.Startup += self.MyApp_Startup
  
  def MyApp_Startup(self, sender, e):
    MessageBox.Show("ApplicationオブジェクトのStartupイベントが発生")

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'with_xaml.xaml')
  
  def Button_Click(self, sender, e):
    self.label1.Content = "ようこそ Iron Python Worldへ"

if __name__ == '__main__':
  app = MyApp()
  app.Run(MyWindow())

 そしてApplication.RunメゾットによりWindowsOSとの対話が開始されるとApplicationはMyWindowのオブジェクトを作成し、表示します。 この後の動作はスクリプトに仕事をされる本来のアプリケーションの部分です。

 Applicationオブジェクトはすべてのウィンドウを管理しているので、通常は最後のウィンドウが閉じたときに自動的Shutdownを呼び出します。 またShutdownの呼び出すタイミングは、ApplicationのShutdownModeプロパティによって設定することができます。
ShudownModeの値 定義
OnLastWindowClose
(default値)
Applicationオブジェクトは、ウィンドウコレクションが空になった時にシャットダウンします。
OnMainWindowClose Applicationオブジェクトは、MainWindowプロパティに割り当てられているウィンドウが閉じたときにシャットダウンします。
OnExplicitShutdown Applicationオブジェクトは、ユーザーコードによってShutDownメゾットが呼び出された場合のみシャットダウンします。

 Application.Shutdownメゾットが実行されるタイミングで、別の動作も付随して行わせたい場合には、その記述をExitイベントに記述します。

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox
import wpf
from System.Windows import Application, Window
class MyApp(Application):
  def __init__(self):
    self.Exit += self.MyApp_Exit
  
  def MyApp_Exit(self, sender, e):
    MessageBox.Show("ApplicationオブジェクトのExitイベントが発生")

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'with_xaml.xaml')
  
  def Button_Click(self, sender, e):
    self.label1.Content = "ようこそ Iron Python Worldへ"

if __name__ == '__main__':
  app = MyApp()
  app.Run(MyWindow())


 これでApplication.Runメゾットの動作が完了します。

 今回、GUIの仕組みとしてWindowOSとの対話することでWindowメッセージが送られてくることを話しましたが、ApplicationはWindowメッセージに合わせて 動作のタイミングを知らせるためにStartupイベントやExitイベントを発生させます。プログラマーは、そのイベントに合わせたScriptを記述することで アプリケーションの動作を制御できます。そのため、GUIに対応したプログラムを、イベントに合わせて動作させることからイベント駆動型プログラムと 読んだりします。

 最後に、インタラクティブシェルからApplicationのインスタンスを2つ作ってみてください。
>>> import wpf
>>> from System.Windows import Application
>>> app1 = Application()
>>> app2 = Application()
Traceback (most recent call last):
File "<stdin>", line 1, in &ly;module>
SystemError: 同じ AppDomain 内で、複数の System.Windows.Application インスタンスを作成することはできません。
>>> 
2つ目を作った際に叱られちゃいましたね。アプリケーションを管理するオブジェクトが2つになると管理できなくなるため、必ず一つの アプリケーションには、一つのApplicationインスタンスしか存在しません。