AOISOMEリセット&コミットしました

AOISOMEの方は一旦クリアし、XRCedで作成したファイルだけの状態にしました(Rev.22)。

これからの予定としては

  • ボタンでTreeViewにノード追加するイベント
  • テスト用ファイルの読み書き

あたりをやってみます。その際に、AoisoNodeクラスは既存のものを使いまわします。また、Logicクラスも流用し、最終的にはPyGtkとwxPythonどちらでも共有できるソースをできるだけ作りたいと思います。うまくいけばAOISORAに移植。最終的には

$ python aoisora.py -gtk
$ python aoisora.py -wx

見たいに起動オプションでツールキットを選べるとか。まぁそこまでやるかどうかは未定ですが。

XRCedで生成されたソースについて

XRCedでGUIを作ったら、xrcファイルとpythonファイルが作られるわけですが、このpythonファイルをどうするかが問題です。直接編集すると次回ジェネレートするときに困ります。しかし良く見てみると大事なことはだいたいxrcファイルに書いてあるので、GUIを作り替えてもpythonファイルの方は毎回ジェネレートしなくても良さそうです。イベントハンドラの関連付けを手動でやることになりますが、その程度であれば直接編集できるメリットの方が大きいでしょう。

また、このような便利なユーティリティを作っている方がいました。
http://python.matrix.jp/projects/wxPython/helper.html

これを使えばイベントとメソッドの紐づけが楽になります。

というわけで、XRCedでの編集では

  • 最初の一回だけpythonソースを書き出す。このためメインフレームの名前はこの時点で確定させる。
  • その後の編集ではxrcファイルだけ保存。
  • 上記サイトのwx_utils.pyのbinderを使わせてもらう。

というのが一番理想的な開発手法ではないかと思います。ただしこのwx_utils.pyはライセンスが不明です。もし使うことになったら作者に聞いてみます。

続・XRCedで生成されたソースについて

なんかジェネレートされたPythonファイルはいらないような気がしてきた。

Gladeと同じようにXMLを読み込むところからコーディングしても別に手間じゃないし、自分で書いたソースの方が読みやすい。
シンプルなFrameならxrcファイルとAppクラスだけでいける。

import sys
import wx
import wx.xrc as xrc

print "aoiso start"
print __name__

class AoisoApp(wx.App):

    def OnInit(self):
        self.res = xrc.XmlResource('aoisome.xrc')
        self.init_frame()
        return True

    def init_frame(self):
        self.frame = self.res.LoadFrame(None, 'MainFrame')
        self.frame.Bind(wx.EVT_MENU, self.OnFileNewClick, id=xrc.XRCID('FILE_NEW'))
        self.frame.SetSize((700,500))
        self.frame.SetPosition((200,200))
        self.frame.Show()

    def OnFileNewClick(self, event):
        print "file_new"


if __name__ == "__main__":
    print "Execute AOISO"
    app = AoisoApp(False)
    app.MainLoop()

MainFrameをちゃんと宣言してメソッドを追加したりしたい場合は、こんな感じ。

import sys
import wx
import wx.xrc as xrc

print "aoiso start"
print __name__

class MainFrame(wx.Frame):
    def __init__(self, app, parent=None):
        pre = wx.PreFrame()
        app.res.LoadOnFrame(pre, parent, "MainFrame")
        self.PostCreate(pre)
        self.Bind(wx.EVT_MENU, app.OnFileNewClick, id=xrc.XRCID('FILE_NEW'))
        self.SetSize((700,500))
        self.SetPosition((200,200))

class AoisoApp(wx.App):

    def OnInit(self):
        self.res = xrc.XmlResource('aoisome.xrc')
        self.frame = MainFrame(self)
        self.frame.Show()
        return True

    def OnFileNewClick(self, event):
        print "file_new"


if __name__ == "__main__":
    print "Execute AOISO"
    app = AoisoApp(False)
    app.MainLoop()

最初はFrameの引数parentにApp自身を渡してやればいいのではと思ったのですが、parentは本来そういうものではないので、LoadOnFrameのparentにNoneを渡したりとトリッキーな記述が必要になります。ここでは__init__の引数を増やしました。

あと、分かってしまえばなんということはないのですが、イベントが取れなくてちょっとハマりました。MenuやToolBarのイベントはEVT_BUTTONではなくEVT_MENUなんですね。

ここまでコミットしました(Rev.23)。

TreeViewにアイコン表示

やることは、TreeViewの生成時に

column = gtk.TreeViewColumn() 
column.set_title('item')
render_pixbuf = gtk.CellRendererPixbuf()
column.pack_start(render_pixbuf,expand=False)
column.add_attribute(render_pixbuf,'pixbuf',c.COL_ICON)
render_text = gtk.CellRendererText()
column.pack_start(render_text,expand=True)
column.add_attribute(render_text,'text',c.COL_TEXT)
self.append_column(column)

こんな感じでテキストの前にpixbufを追加してやるだけでした。あとは各TreeIterのカラムに対してpixbufをset_valueしてやればアイコンが表示されます。

というわけで、コミット(Rev.21)。・・・なんですが、前回のつづきでソースを整理しているうちにあちこちいじったので変更箇所を追うのは結構大変です。モデルに関してもTreeStoreを直接使うのでなく派生クラスを使うことにしました。おかげでだいぶモデルとビューとロジックを分離できてきたかな。

wxPythonも使ってみるか

カテゴリをちょっと変更しました。

さて、PyGtkでの開発のめどはたったんですが、py2exeの豆腐問題とか、GtkのダイアログはWindowsユーザには馴染めないとか、いろんな課題が残されています。元々Linuxで使うためのソフトとして開発をしているわけですが、配布し始めたら9割くらいはWindowsユーザじゃないかと思うので、この辺はちゃんと考えなければな、というところです。

そこで、開発中のAOISORAはちょっと中断し、AOISOMEのほうではwxPythonに浮気してみようかと思います。要するにこれまでGtkで作ってきたものと同じものを一からwxWidgetsで書き直してみようというわけです。

そんなこんなでwxGladeと格闘していたのですが、sizer独特すぎてワカンネ・・・。Gtkとそんなに違わないと思っていたのですが甘かった。wxGladeの使い方の前にwxWidgetsのレイアウトについて勉強する必要があるようです。

AOISORA 0.0.4 リリースしました。

次の作業に入る前に一旦今の状態(Rev.21)をAOISORA-0.0.4としてリリースします。

0.0.3からの目だった変更点はツリー上にアイコンが表示されるようになったくらいですが、内部的にはかなり変わっています。また、今のところ文字化けして実質使えないのですが、Windows用バイナリ(exe)も今回から配布することにしました。

sizerメモ

画面リサイズに追随するかどうかの決め手になるパラメータはProportionとwxEXPAND。

Sizerの方向に関してはProportionが0だと固定、1以上だとリサイズに追随。通常の2分割の場合は片方が0、もう一方が1になる。3分割以上を使う場合は、広げたいペインだけ1にする。広げたいペインが複数ある場合は比率を指定する。全部1なら均等。

Sizerの方向じゃない方の配置に関してはAlignment(wxHOGE)を使用する。wxEXPANDでいっぱいいっぱいに広がる。

wxGladeでは、配置したWidgetのProportionが場合によって0になったり1になったりする。一見親切なようだけどあまり的確ではないので、全部調べて手修正する。

多分こんな感じ。

wxGladeをPythonで使う方法

Gladeの場合はPythonのスクリプトから*.gladeファイルを直接読み込んで使うが、wxGladeの場合はwxGladeからPythonファイルをジェネレートしてそれを使う。こっちの方が全部Pythonで読めて便利かも。

しかし、wxGladeでGUIいじる度にジェネレートするとすればPythonのソースはGUI部分に関しては全くいじれないし、ジェネレートされたPythonソースをガンガンいじるとすればwxGladeの恩恵にあずかれるのは開発の初期だけということになる。うーん、どっちがいいんだろう。


ちなみにジェネレートされたPythonソースにはメインループが書かれているので、そのまま実行すればメインウインドウが起動する。Pythonを一行も書かずにここまでたどり着けるというのは結構すごい。いやDelphiとかLazarusでもできるんだけどね。Gladeとはだいぶ違うなぁと。

XRCedにしよう

wxGladeを使っていたらすぐに問題にぶつかった。wxGladeでは、ボタンなどの画像の指定がファイル名でしかできない(多分)。Gladeのようにstock画像を呼び出せない。最終的にはすべての画像アイコンを自作する予定なのでそれはそれでもいいのかもしれないが、開発途中にはとりあえず仮のアイコンを選べた方が便利だ。

そこでwxWidgets付属のXRCedを使ってみた。これはGUIがプレビューされて一見RADっぽいがそうじゃない。XMLツリーを編集するためのGUIエディタだ。正直言ってあまり親切なツールじゃない。特に何かウィジェットを間違って配置しているときにはプレビューする際に「それムリよ」と言われるのがウザい(先に教えてくれよw)。が、wxGladeよりも良い点もいくつかある。まず、Sizerの行(列)の追加が不要な点。Sizer上にウィジェットをガンガン追加していき、あとでProportionとwxEXPANDで調整する。Sizerの縦横変更もこちらの方が直感的。それから本題のstock画像については、wxART_HOGEを指定できる。ほんとは一覧表に画像そのものも表示されてるといいんだけど、まぁすぐプレビューされるしいいか。

というわけで、wxGladeは中止。GUIエディタはXRCedにします。

書き忘れてましたが、「XRCedは日本語が使えない」という情報がいくつかネット上で見受けられますが、ちゃんと使えます。