wxPython入門(大阪Pythonユーザの集まり2014/03)

50 %
50 %
Information about wxPython入門(大阪Pythonユーザの集まり2014/03)
Technology

Published on March 14, 2014

Author: YasushiMasuda

Source: slideshare.net

Description

大阪Pythonユーザの集まり 2014/03 で発表した、wxPython入門のスライドです。

wxPython入門 増田 (@whosaysni)

自己紹介 •  増田 泰 (@whosaysni) •  Google+ つかってません •  GitHub<<<BitBucket •  某バイオベンチャー勤務 •  ドキュメント翻訳とかDjango本とか •  一般社団法人PyConJP理事 •  PyConJPきてください 9/13-15 •  http://2014.pycon.jp/

wxPython •  GUIライブラリ •  wxWidgetsのPythonラッパー •  SWIG使ってる •  各OSのGUIコンポーネントを使う •  OSXならCocoa •  Windowsならwin32 •  LinuxならGTK •  wxWidgetsライセンス •  条文はLGPL2だが、バイナリの配布時に独自 の使用許諾ができる例外条項がある

まずは基本

GUIプログラム •  シェルで起動 •  操作(イベント)に合わせてハ ンドラが呼ばれる •  ハンドラがUIコンポーネントを 操作する •  次のイベント待ち GUIプログラミングって? スクリプト •  シェルで起動 •  処理を逐次実行 •  最後の処理を終えたら終了 •  シェルに制御を戻す Webフレームワーク •  Webサーバが起動 •  リクエストに合わせて ハンドラが呼ばれる •  ハンドラがレスポンス返す •  次のリクエスト待ち ディス パッチ ハンドラ ビュー 操作 イベント ループ

ウィジェット Widget •  ボタンとかウィンドウとか、画面の構成要素 •  UIを実際に描画する(自動的にね) •  ユーザ操作に応じてイベントを生成する •  wxPython/wxWidget •  ほとんどのウィジェットがクラスで階層化 wxObject ... wxWindow wxControl wxBu4on wxSta7cText wxMenu ... wxPanel wxTopLevelWindow wxFrame wxDialog

イベントループ while len(event_q): ev = event_q.pop() handler = dispatch(ev) if handler: handler(ev) イベントキュー イベントループロジック GUI操作 その他   イベント イベントハンドラ イベントハンドラ イベントハンドラ たいていのGUIフレームワークには、 ・イベントループを実行する関数 ・ハンドラを登録する関数 があり、(1)ハンドラを定義して(2)ディ スパッチャに登録し、(3)イベントルー プを呼ぶようになっている。

wxPythonのイベントループ >>> import wx >>> app = wx.App() # Appインスタンス >>> frame = wx.Frame(None) # ウィンドウつくる >>> app.SetTopWindow(frame) >>> frame.Show(True) True >>> app.MainLoop() # ここがメインループ (ループ中。ウィンドウ閉じるまで戻りませんw)

アプリは wxApp() をサブクラス化する # coding: utf-8 import wx class MyApp(wx.App): def OnInit(self): #Appインスタンス生成時に呼び出される self.frame = wx.Frame(None) # 何でも属性にできる。Python最高ヤッホウ self.frame.SetTitle(u'よろしくwxさん') self.SetTopWindow(self.frame) self.frame.Show(True) return True # お約束。重要 if __name__=='__main__': app = MyApp() app.MainLoop()

GUIのレイアウト

GUIのレイアウト •  ウィジェットをウィンドウのどこに配置するか •  位置(x, y)と大きさ(w, h) •  配置(右寄せ、左寄せ) •  伸長(ウィンドウに合わせてサイズ変更) •  グループ化(OK/Cancelボタンとか) •  wxWidgetsでは、Sizerオブジェクトがレイアウ トを制御する •  ウィンドウにSizerを登録する

BoxSizer()があれば無問題!だと思う 硬派のSizer道(嘘)

BoxSizer wx.BoxSizer(wx.VERTICAL) wx.BoxSizer(wx.HORIZONTAL) v_box = wx.BoxSizer(wx.VERTICAL) v_box.Add(widget_A) v_box.Add(widget_B) h_box = wx.BoxSizer(wx.HORIZONTAL) h_box.Add(v_box) h_box.Add(widget_C) VERTICAL HORIZONTAL C A B

BoxSizer def OnInit(self): ... label = wx.StaticText( self.frame, -1, u'ボタン三兄弟', style=wx.ALIGN_CENTER) btn_1 = wx.Button(self.frame, -1, u'ボタン長男') btn_2 = wx.Button(self.frame, -1, u'ボタン次男 ') btn_3 = wx.Button(self.frame, -1, u'ボタン三男') sizer = wx.BoxSizer(wx.VERTICAL) btn_sizer = wx.BoxSizer(wx.HORIZONTAL) btn_sizer.Add(btn_1, 3, wx.ALL¦wx.EXPAND, 30) btn_sizer.Add(btn_2, 2, wx.ALL¦wx.EXPAND, 20) btn_sizer.Add(btn_3, 1, wx.ALL¦wx.EXPAND, 10) sizer.Add(label, 0, wx.ALL¦wx.EXPAND, 50) sizer.Add(btn_sizer, 0, wx.ALL¦wx.EXPAND, 0) self.frame.SetSizer(sizer) self.frame.Fit() 50 50 50 30 30 30 20 20 10 10 10 20 20 (上揃え)

イベント処理

おさらい イベントキュー イベントループロジック GUI操作 その他   イベント イベントハンドラ イベントハンドラ イベントハンドラ GUIプログラム •  シェルで起動 •  操作(イベント)に合わせてハ ンドラが呼ばれる •  ハンドラがUIコンポーネントを 操作する •  次のイベント待ち ディス パッチ ハンドラ ビュー 操作 イベント ループ

イベントハンドラはどこにでも書ける def event_handler(evt): #普通の関数 ... •  evt: イベントオブジェクト •  イベントの種類 •  パラメタ(マウス座標など) •  その他、発生元のウィジェットなどの情報 •  wx.Appのメソッドとして書くのがいい •  evtから他の変数引っ張るの大変 •  詳しくはあとで

イベントをハンドラに結びつける ウィジェットの Bind() メソッドをつかう 例: widget.Bind(wx.EVT_MOUSE, handler) •  この操作で、 •  「widget」が •  「マウスイベント」を受け取ると •  handler を呼び出す •  アプリのインスタンスメソッドの場合 •  def handler(self, evt): ... •  self.bind(wx.EVT_MOUSE, self.handler)

ハンドラの中でウィジェットを操作する def OnInit(self): ... self.btn = wx.Button(self.frame, -1, u'押さないで') self.btn.Bind(wx.EVT_BUTTON, self.OnOsunaPressed) def OnOsunaPressed(self, evt): self.btn.SetLabel(u'マジで'+self.btn.GetLabel()) self.frame.Fit()

tips

アプリケーションの参照をとる •  Appクラスに変数置いてるんだけど。  →いいね! •  モジュール変数使って渡していい? ダメです •  ウィンドウにAppのインスタンス渡す?ダメ _人人人人人人人_ > wx.GetApp() <  ̄Y^Y^Y^Y^Y^Y ̄ 実例はあとで

大きなアプリを書くとき •  ウィンドウやダイアログがたくさんある •  ウィンドウごとにモジュールを作る •  wx.Dialogやwx.Frameをサブクラス化する ほとんどのウィジェットをPurePythonでサブクラス化OK! Python完全勝利(S)! •  ウィンドウ固有の処理はモジュールに押し込める •  モジュールの if __module__==__main__ で wx.App を作ってアプリ化する これで、画面構成モジュール単位で開発できます!

MVC的な住み分け •  Model 基本、Appインスタンス経由で参照する •  Controller ビジネスロジックはAppインスタンス ウィジェットの細かい操作が多ければ 別モジュールに書く テストの住み分け的にも大事 •  View ウィジェットに複雑なデフォルト設定を したいなら別モジュールに書くのがいい

ダメじゃないけどダメな例 (app.py) def OnInit(self): self.main_window = wx.Frame(....) self.main_window_root_pane = wx.Panel(...) self.main_window_sizer = wx.BoxSizer(...) self.main_window_sizer.Add(self.main_window_root_pane) self.main_window.SetSizer(self.main_window_sizer) self.main_window_lr_sizer = wx.BoxSizer(...) self.main_window_left_pane = ... ....

いい感じな例 (app.py) import wx from main_window import MainWindow class MyApp(wx.App): def OnInit(self): self.main_window = MainWindow(...) self.SetTopWindow(self.main_window) ... self.main_window.some_method(...) ... return True def on_main_window_submit(self, evt): ... (main_window.py) import wx class MainWindow(wx.Frame): def __init__(self, *args, **kw): wx.Frame.__init__(self, *args, **kw) self.root_pane = wx.Panel(...) self.sizer = wx.BoxSizer(...) ... self.Bind(SOMEEVENT, self.app.on_main_window_submit) @property def app(self): return wx.GetApp() def some_method(self, ...) ... do something ... こっちは   プレゼンテーション寄り こっちは ビジネスロジック寄り  

いい感じな例 (app.py) import wx from main_window import MainWindow class MyApp(wx.App): def OnInit(self): self.main_window = MainWindow(...) self.SetTopWindow(self.main_window) ... self.main_window.some_method(...) ... return True def on_main_window_submit(self, evt): ... (main_window.py) import wx class MainWindow(wx.Frame): def __init__(self, *args, **kw): wx.Frame.__init__(self, *args, **kw) self.root_pane = wx.Panel(...) self.sizer = wx.BoxSizer(...) ... self.Bind(SOMEEVENT, self.app.on_main_window_submit) @property def app(self): return wx.GetApp() def some_method(self, ...) ... do something ... こっちは   プレゼンテーション寄り こっちは ビジネスロジック寄り  

モジュールのモック化 (main_window.py) import wx class MainWindow(wx.Frame): def __init__(self, *args, **kw): wx.Frame.__init__(self, *args, **kw) self.root_pane = wx.Panel(...) self.sizer = wx.BoxSizer(...) ... self.Bind(SOMEEVENT, self.app.on_main_window_submit) @property def app(self): return wx.GetApp() ... (続く) (続き) ... # ここからモック駆動用コード if __name__== __main__ : class DemoApp(wx.App): def on_main_window_submit(self, evt): ... do some nothing ... ... # モックアプリを作って走らせる app = DemoApp() w = MainWindow(None) app.main_window = w app.SetTopWindow(w) app.MainLoop() 「ホホウ。もう出来てるじゃないか。じゃあ工数減ら して見積り再提出してもらえんかね」とお客様に言 われても当方は一切責任をもちません

おすすめツール •  wxPython Demo http://www.wxpython.org/download.php Demoを見れば大抵のウィジェットは使える •  Dash https://itunes.apple.com/jp/app/dash-docs- snippets/id458034879?mt=12 wxWidets のドキュメントがあります

enjoy!

Add a comment

Related presentations

Related pages

wxpython 入門 13

wxPython入門(大阪Pythonユーザの集まり2014/03)-SlideShare. wxpython 入門 ...
Read more

wxpython python 3 100

wxPython入門(大阪Pythonユーザの集まり2014/03)-SlideShare It allows Python programmers to create programs with a robust,highly functional ...
Read more

wxpython license 28

wxPython入門(大阪Pythonユーザの集まり2014/03 ...
Read more

wxpython library 51

wxPython入門(大阪Pythonユーザの集まり2014/03) - SlideShare wxWidgets モ wxPython ...
Read more

wxpython 開発環境 27

wxPython入門(大阪Pythonユーザの集まり2014/03) - SlideShare wxPythonはPython ...
Read more

BTY備忘録 » Blog Archive » wxPython wx.Timerを ...

wxPython入門(大阪Pythonユーザの集まり2014/03 ...
Read more