IronPython で WPF

IronPython には nt という os の代替モジュールがあることを今更知った。
ということは前回のコードは

# -*- coding: UTF-8 -*-

# 環境変数の書き出し

import nt

keys = nt.environ.keys()
result = ""
for key in keys:
	result += key + "\n" + nt.environ[key] + "\n\n"

f = open("env2.txt", "w")
f.write(result)
f.close()

あーあ、os を nt に書き換えるだけで動いてしまったお。
open() とかは組み込み関数だからそのまま使えるし。

とはいえ IronPython ではコッチで書く人はほとんどいないだろう。
C# コードからの変換ばかりやるはめになるのは目に見えているし。

ということで

の本で WPF アプリのコードがあまりに不親切だったので補完。
部品を作るのにいきなり XAML を利用では IronPython の意味が無いでしょみたく。
XAMLPAD では Glade のようにはいかないと思うし、機能がショボすぎる。

マイレビューを一つ、CPython コードを書くのにも少し役に立ったよと。
ちなみに上記の nt モジュールの存在はコレを読み直して知った…
しかし mono の本同様にコレしかなく選べない状態が続いているのは悲しい。

さて最小限のコードを書いてみる。

# -*- coding: UTF-8 -*-

import clr

# 最小限下記ライブラリ(dll)が必要
clr.AddReferenceByPartialName("PresentationCore")
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("WindowsBase")

import System

w = System.Windows.Window()
w.Title = "実験"
a = System.Windows.Application()
a.Run(w)

最小限のライブラリとは VC# とかを持っている人なら解るかな?
ソリューションエクスプローラにある参照設定以下のことね。
VC# なら右クリックして「参照の追加」をするけど IronPython はコードで行う。

se

本当は System も必要だけど最初から含まれているっぽい。

後、上記の本ではいきなり from 文を使っているけど理解してから使いましょう。
Window や Application というクラスは System.Windows 名前空間にあります。

知っていると思うけど Python の名前空間はモジュール名そのままである。
partial 指定ができないのが場合によっては辛いかもしれない。
boo という Python そっくりな言語はココの画像を見るとできるっぽい。

【ハウツー】F#、IronPython、Booまで使えるフリーの統合開発環境「SharpDevelop」 (3) 利用できるプログラミング言語 | エンタープライズ | マイコミジャーナル

まあそれはよくて。
上記を拡張しても後々で困るのでさっさとクラスに変更します。

# -*- coding: UTF-8 -*-

import clr

# 最小限下記ライブラリ(dll)が必要
clr.AddReferenceByPartialName("PresentationCore")
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("WindowsBase")

from System import *
from System.Windows import *

class TestWin(Window):
    def __init__(self):
        self.Title = "class の実験"
        self.Closing += self.onClosing
    
    def onClosing(self, sender, e):
        MessageBox.Show("閉じます")

if __name__ == "__main__":
    w = TestWin()
    a = Application()
    a.Run(w)

やっぱり面倒なので from を利用、これで C# の using と同じ意味。

VC# で作るのと同じように Window を継承したクラスを __main__ で作る。
最後に Application インスタンスの Run() にぶち込めばクラス化は完了である。
これで C# コードからの変換が簡単になりました。

ついでに終了時にダイアログを出すようにハンドラを追加してみた。
Python のクラスなので引数に必ず self が必要です、よく忘れるんだこれが。

最後にコントロールを追加してみます。
XAML を使わずにコードで作る方法をば。

# -*- coding: UTF-8 -*-

import clr

# 最小限下記ライブラリ(dll)が必要
clr.AddReferenceByPartialName("PresentationCore")
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("WindowsBase")

from System import *
from System.Windows import *
from System.Windows.Controls import *

class TestWin(Window):
    def __init__(self):
        self.Title = "Controls"
        # ボタン作成及びクリックハンドラ登録
        button = Button()
        button.Content = "ボタンだよ"
        button.Click += self.onClick
        # 一行エディットの作成
        # 内容を他で使うのでアトリビュートにしておく
        self.textbox = TextBox()
        self.textbox.Text = "なんか書け"
        # TextBlock の作成
        tb = TextBlock()
        tb.Text = "何か書き込んでボタンを押してね"
        # レイアウタを作成してこれらをセット
        sp = StackPanel()
        sp.Orientation = Orientation.Vertical
        sp.Children.Add(button)
        sp.Children.Add(self.textbox)
        sp.Children.Add(tb)
        # レイアウタを Window にセット
        self.Content = sp
        # この指定でコンテンツの大きさ固定なウインドウになる
        self.SizeToContent = SizeToContent.WidthAndHeight
        self.ResizeMode = ResizeMode.NoResize
    
    def onClick(self, sender, e):
        MessageBox.Show(self.textbox.Text)

if __name__ == "__main__":
    a = Application()
    a.Run(TestWin())

Button 等のクラスは System.Windows.Controls にあるので import する。
Window や Button に何かを乗せるには Content プロパティに代入する。
レイアウタにコントロールを追加するには Children.Add() メソッドを利用する。
という簡単な例である、最後に Run() の中で Window を作る小技をば。

seira

C# でウインドウをコードで作った人なら解るだろうけどほとんど同じに書けます。
C++ から Pascal への変換を経験した人なら「え?それだけ???」ですよね。
今回はここまで。