PythonのGUIアプリを(VB.NETで)書こう

どーも。今回はPythonのクラスをVB.NETから呼び出して、既存PythonソースとGUIとの橋渡しをしたいと思います。


Pythonベジェ曲線クラスをVB.NETから呼び出してハートマークを書いたの図

PythonでのGUI開発

Pythonで書いたスクリプトの機能をGUI化したい。そういう時の選択肢は大体こんなもんじゃないでしょうか。

名前 説明
Tkinter Pythonディストリビューションの標準ライブラリ
PyGTK クロスプラットフォームGUIライブラリGTKPythonバインディング
wxPython クロスプラットフォームGUIライブラリwxWidgetsPythonバインディング
PyQt 同じくGUIライブラリのQtのPythonバインディング
PySide PyQtのライセンス違いらしい。

で、TkinterwxPythonをいじって、PythonGUIプログラムを組むときの問題点だなーと感じたのが

  • GUIプログラミングは関連するクラスが多いので、どういう時どのクラスを利用すればいいのか、どのプロパティを変更すればいいのかが、すぐにはわからない。
  • にも関わらず、ライブラリのドキュメントが不足している、日本語の情報どころか英語の情報もほとんど無い
  • プロパティの名前などいちいち覚えていられないのに、エディタ、IDEの補完が弱い(遅い)
  • クロスプラットフォームのライブラリだとしばしばバグに遭遇する
  • GUIデザイナの貧弱さ、不安定さ

→ から...全然進まずに困っちゃうという。特にGUIデザイナの貧弱さは悲惨で、はじめから画面レイアウトを入念に考えて組んで、実際に使って見て調整、変更する際に結構大きく変更する必要が出たりして本当にだるい。wxPythonとか、wxWidgetsを理解してないとドキュメントだけ読んでも訳分からんとこ多いし。

.NETでやればいいんじゃね?

全然資料が無いところを暗中模索で無駄に時間を使ってうがーとなるのを繰り返すうちに、段々、散々時間かけてTkinterとかいう謎のライブラリを使ったりwxPythonみたいにまともに資料が無いものを使うよりなんかもう.NETでやればいいんじゃないのかなと考えるようになりました。どうせPyQtとかもアレなんだろ!!!みたいな。
ただ、機能に関しては既にPythonで実装しているので、.NETで実装しなおすような事はしたくない。そこで。
IronPythonで既存Pythonスクリプトのロジックを動かし、VB.NETでUIを操作するというアプローチPythonGUIアプリを作ってみたいと思います。

VB.NETなら

  • ドキュメントが豊富
  • 安定してる
  • すぐ使える(Pythonが分かるなら、構文だけならほとんど労力を割かずに覚えられる

ので、適当にぐぐってコピペしてIronPythonに橋渡ししてやれば簡単にGUIをつけられるはず。



関連

IronPythonの世界 (Windows Script Programming)

IronPythonの世界 (Windows Script Programming)

IronPythonについて書かれてるらしい。今回、VB.NET - IronPython間の連携部分については割とネットで検索してトライアンドエラーの暗中模索な感じだったので(結局それか)体系的にまとまった本がほしいなぁ。



用意するもの

IronPythonのインストール時に、他の言語からIronPythonを利用するためのDLLファイル群が同時にインストールされます。

VB.NETアプリ実行時のIronPythonとの連携準備

  1. VB.NETのプロジェクトに、IronPythonディレクトリを丸ごと追加(コピー)する。
  2. Libディレクトリとdllファイルを残してすべて削除する。

  1. [プロジェクト]→[参照の追加]から参照タブを選択してIronPythonのフォルダ以下にあるdllを全て追加する


VB.NET - IronPythonの連携

ここまで書いて置いてまだよく分かってないのですが最低限の部分だけ。

予め、プロジェクトに「PythonLibrary」という名前のディレクトリを用意して以下のスクリプトを配置されているとします。

# Greeting.py
class Greeting:
    def __init__(self):
        self.hist = []
    def greeting(self, name):
        self.hist.append(name)
        return 'hello %s!' % name
    def history(self):
        return self.hist

VB.NET側ではIronPythonの実行エンジンを作成してPythonスクリプトを読み込んで、インスタンスを作成したりしてデータを受け渡しします。

Imports Microsoft.Scripting
Imports Microsoft.Scripting.Hosting
Imports IronPython.Hosting

' ...略
    Dim engine As ScriptEngine = Python.CreateEngine()
    ' サーチパス設定(モジュールのインポートに必要)
    engine.SetSearchPaths(New String() {"..\..\IronPython 2.7\Lib", "..\..\PythonLibrary", "."})
    Dim scope As ScriptScope
    ' Pythonファイル読み込み
    scope = engine.Runtime.ImportModule("Greeting") ' 外部ライブラリ読み込み
' ...略
    ' インスタンス作成
    Dim cls As Object = engine.Operations.Invoke(scope.GetVariable("Greeter"))
' ...略
    ' メソッド呼び出し
    Dim str As String = engine.Operations.InvokeMember(cls, "greeting", New Object() {"alice"})
    ' listが戻り値の場合
    Dim lst As IronPython.Runtime.List = engine.Operations.InvokeMember(cls, "history", New Object() {})
    

こんな感じ。BeautifulSoup等の外部ライブラリなどもこのディレクトリに入れておけば(あるいは他のディレクトリを掘ってサーチパスに追加すれば)、サードパーティーのライブラリもインポートして使えるようになります。

連携例

前に「Pythonでベジェ曲線クラスを実装してwxPythonで動かす」で実装したベジェ曲線の計算クラスの機能に、指定された4点からなる3次のベジェ曲線を描画するGUIプログラムを作ってみました。コードは以下に

https://gist.github.com/1303534

こんな事ができます。

  • 4点をクリックするとそれらからなる3次のベジェ曲線を描画する。
  • 1度描画された曲線の制御点は、シフトボタンを押しながらドラッグすると移動できる。
  • クリアボタンを押すと全ての曲線と編集中の点がクリアされる。


Shiftを押しながらドラッグで下へ移動すると・・・

制御点が移動する