Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
wxPython入門
増田 (@whosaysni)
自己紹介
•  増田 泰 (@whosaysni)
•  Google+ つかってません
•  GitHub<<<BitBucket
•  某バイオベンチャー勤務
•  ドキュメント翻訳とかDjango本とか
•  一般社団法人PyConJP理...
wxPython
•  GUIライブラリ
•  wxWidgetsのPythonラッパー
•  SWIG使ってる
•  各OSのGUIコンポーネントを使う
•  OSXならCocoa
•  Windowsならwin32
•  LinuxならGT...
まずは基本
GUIプログラム
•  シェルで起動
•  操作(イベント)に合わせてハ
ンドラが呼ばれる
•  ハンドラがUIコンポーネントを
操作する
•  次のイベント待ち
GUIプログラミングって?
スクリプト
•  シェルで起動
•  処理を逐次実行...
ウィジェット Widget
•  ボタンとかウィンドウとか、画面の構成要素
•  UIを実際に描画する(自動的にね)
•  ユーザ操作に応じてイベントを生成する
•  wxPython/wxWidget
•  ほとんどのウィジェットがクラスで階...
イベントループ
while len(event_q):
ev = event_q.pop()
handler = dispatch(ev)
if handler:
handler(ev)
イベントキュー	
イベントループロジック	
GUI操作	...
wxPythonのイベントループ
>>> import wx
>>> app = wx.App() # Appインスタンス
>>> frame = wx.Frame(None) # ウィンドウつくる
>>> app.SetTopWindow(f...
アプリは wxApp() をサブクラス化する
# coding: utf-8
import wx
class MyApp(wx.App):
def OnInit(self): #Appインスタンス生成時に呼び出される
self.frame = ...
GUIのレイアウト
GUIのレイアウト
•  ウィジェットをウィンドウのどこに配置するか
•  位置(x, y)と大きさ(w, h)
•  配置(右寄せ、左寄せ)
•  伸長(ウィンドウに合わせてサイズ変更)
•  グループ化(OK/Cancelボタンとか)
• ...
BoxSizer()があれば無問題!だと思う
硬派のSizer道(嘘)
BoxSizer
wx.BoxSizer(wx.VERTICAL)
wx.BoxSizer(wx.HORIZONTAL)
v_box = wx.BoxSizer(wx.VERTICAL)
v_box.Add(widget_A)
v_box.Ad...
BoxSizer
def OnInit(self):
...
label = wx.StaticText(
self.frame, -1, u'ボタン三兄弟', style=wx.ALIGN_CENTER)
btn_1 = wx.Button(...
イベント処理
おさらい
イベントキュー	
イベントループロジック	
GUI操作	
その他	
  
イベント	
イベントハンドラ	
イベントハンドラ	
イベントハンドラ	
GUIプログラム
•  シェルで起動
•  操作(イベント)に合わせてハ
ンドラが呼ばれ...
イベントハンドラはどこにでも書ける
def event_handler(evt): #普通の関数
...
•  evt: イベントオブジェクト
•  イベントの種類
•  パラメタ(マウス座標など)
•  その他、発生元のウィジェットなどの情報...
イベントをハンドラに結びつける
ウィジェットの Bind() メソッドをつかう
例: widget.Bind(wx.EVT_MOUSE, handler)
•  この操作で、
•  「widget」が
•  「マウスイベント」を受け取ると
• ...
ハンドラの中でウィジェットを操作する
def OnInit(self):
...
self.btn = wx.Button(self.frame, -1, u'押さないで')
self.btn.Bind(wx.EVT_BUTTON, self....
tips
アプリケーションの参照をとる
•  Appクラスに変数置いてるんだけど。
 →いいね!
•  モジュール変数使って渡していい? ダメです
•  ウィンドウにAppのインスタンス渡す?ダメ
_人人人人人人人_
> wx.GetApp() <
 ̄Y...
大きなアプリを書くとき
•  ウィンドウやダイアログがたくさんある
•  ウィンドウごとにモジュールを作る
•  wx.Dialogやwx.Frameをサブクラス化する
ほとんどのウィジェットをPurePythonでサブクラス化OK!
Pyth...
MVC的な住み分け
•  Model
基本、Appインスタンス経由で参照する
•  Controller
ビジネスロジックはAppインスタンス
ウィジェットの細かい操作が多ければ
別モジュールに書く
テストの住み分け的にも大事
•  View
...
ダメじゃないけどダメな例
(app.py)
def OnInit(self):
self.main_window = wx.Frame(....)
self.main_window_root_pane = wx.Panel(...)
self....
いい感じな例
(app.py)
import wx
from main_window import MainWindow
class MyApp(wx.App):
def OnInit(self):
self.main_window = Mai...
いい感じな例
(app.py)
import wx
from main_window import MainWindow
class MyApp(wx.App):
def OnInit(self):
self.main_window = Mai...
モジュールのモック化
(main_window.py)
import wx
class MainWindow(wx.Frame):
def __init__(self, *args, **kw):
wx.Frame.__init__(self,...
おすすめツール
•  wxPython Demo
http://www.wxpython.org/download.php
Demoを見れば大抵のウィジェットは使える
•  Dash
https://itunes.apple.com/jp/ap...
enjoy!
Upcoming SlideShare
Loading in …5
×

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

9,577 views

Published on

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

Published in: Technology
  • Dating for everyone is here: ♥♥♥ http://bit.ly/39pMlLF ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Sex in your area is here: ♥♥♥ http://bit.ly/39pMlLF ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

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

  1. 1. wxPython入門 増田 (@whosaysni)
  2. 2. 自己紹介 •  増田 泰 (@whosaysni) •  Google+ つかってません •  GitHub<<<BitBucket •  某バイオベンチャー勤務 •  ドキュメント翻訳とかDjango本とか •  一般社団法人PyConJP理事 •  PyConJPきてください 9/13-15 •  http://2014.pycon.jp/
  3. 3. wxPython •  GUIライブラリ •  wxWidgetsのPythonラッパー •  SWIG使ってる •  各OSのGUIコンポーネントを使う •  OSXならCocoa •  Windowsならwin32 •  LinuxならGTK •  wxWidgetsライセンス •  条文はLGPL2だが、バイナリの配布時に独自 の使用許諾ができる例外条項がある
  4. 4. まずは基本
  5. 5. GUIプログラム •  シェルで起動 •  操作(イベント)に合わせてハ ンドラが呼ばれる •  ハンドラがUIコンポーネントを 操作する •  次のイベント待ち GUIプログラミングって? スクリプト •  シェルで起動 •  処理を逐次実行 •  最後の処理を終えたら終了 •  シェルに制御を戻す Webフレームワーク •  Webサーバが起動 •  リクエストに合わせて ハンドラが呼ばれる •  ハンドラがレスポンス返す •  次のリクエスト待ち ディス パッチ ハンドラ ビュー 操作 イベント ループ
  6. 6. ウィジェット Widget •  ボタンとかウィンドウとか、画面の構成要素 •  UIを実際に描画する(自動的にね) •  ユーザ操作に応じてイベントを生成する •  wxPython/wxWidget •  ほとんどのウィジェットがクラスで階層化 wxObject ... wxWindow wxControl wxBu4on wxSta7cText wxMenu ... wxPanel wxTopLevelWindow wxFrame wxDialog
  7. 7. イベントループ while len(event_q): ev = event_q.pop() handler = dispatch(ev) if handler: handler(ev) イベントキュー イベントループロジック GUI操作 その他   イベント イベントハンドラ イベントハンドラ イベントハンドラ たいていのGUIフレームワークには、 ・イベントループを実行する関数 ・ハンドラを登録する関数 があり、(1)ハンドラを定義して(2)ディ スパッチャに登録し、(3)イベントルー プを呼ぶようになっている。
  8. 8. wxPythonのイベントループ >>> import wx >>> app = wx.App() # Appインスタンス >>> frame = wx.Frame(None) # ウィンドウつくる >>> app.SetTopWindow(frame) >>> frame.Show(True) True >>> app.MainLoop() # ここがメインループ (ループ中。ウィンドウ閉じるまで戻りませんw)
  9. 9. アプリは 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()
  10. 10. GUIのレイアウト
  11. 11. GUIのレイアウト •  ウィジェットをウィンドウのどこに配置するか •  位置(x, y)と大きさ(w, h) •  配置(右寄せ、左寄せ) •  伸長(ウィンドウに合わせてサイズ変更) •  グループ化(OK/Cancelボタンとか) •  wxWidgetsでは、Sizerオブジェクトがレイアウ トを制御する •  ウィンドウにSizerを登録する
  12. 12. BoxSizer()があれば無問題!だと思う 硬派のSizer道(嘘)
  13. 13. 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
  14. 14. 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 (上揃え)
  15. 15. イベント処理
  16. 16. おさらい イベントキュー イベントループロジック GUI操作 その他   イベント イベントハンドラ イベントハンドラ イベントハンドラ GUIプログラム •  シェルで起動 •  操作(イベント)に合わせてハ ンドラが呼ばれる •  ハンドラがUIコンポーネントを 操作する •  次のイベント待ち ディス パッチ ハンドラ ビュー 操作 イベント ループ
  17. 17. イベントハンドラはどこにでも書ける def event_handler(evt): #普通の関数 ... •  evt: イベントオブジェクト •  イベントの種類 •  パラメタ(マウス座標など) •  その他、発生元のウィジェットなどの情報 •  wx.Appのメソッドとして書くのがいい •  evtから他の変数引っ張るの大変 •  詳しくはあとで
  18. 18. イベントをハンドラに結びつける ウィジェットの Bind() メソッドをつかう 例: widget.Bind(wx.EVT_MOUSE, handler) •  この操作で、 •  「widget」が •  「マウスイベント」を受け取ると •  handler を呼び出す •  アプリのインスタンスメソッドの場合 •  def handler(self, evt): ... •  self.bind(wx.EVT_MOUSE, self.handler)
  19. 19. ハンドラの中でウィジェットを操作する 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()
  20. 20. tips
  21. 21. アプリケーションの参照をとる •  Appクラスに変数置いてるんだけど。  →いいね! •  モジュール変数使って渡していい? ダメです •  ウィンドウにAppのインスタンス渡す?ダメ _人人人人人人人_ > wx.GetApp() <  ̄Y^Y^Y^Y^Y^Y ̄ 実例はあとで
  22. 22. 大きなアプリを書くとき •  ウィンドウやダイアログがたくさんある •  ウィンドウごとにモジュールを作る •  wx.Dialogやwx.Frameをサブクラス化する ほとんどのウィジェットをPurePythonでサブクラス化OK! Python完全勝利(S)! •  ウィンドウ固有の処理はモジュールに押し込める •  モジュールの if __module__==__main__ で wx.App を作ってアプリ化する これで、画面構成モジュール単位で開発できます!
  23. 23. MVC的な住み分け •  Model 基本、Appインスタンス経由で参照する •  Controller ビジネスロジックはAppインスタンス ウィジェットの細かい操作が多ければ 別モジュールに書く テストの住み分け的にも大事 •  View ウィジェットに複雑なデフォルト設定を したいなら別モジュールに書くのがいい
  24. 24. ダメじゃないけどダメな例 (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 = ... ....
  25. 25. いい感じな例 (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 ... こっちは   プレゼンテーション寄り こっちは ビジネスロジック寄り  
  26. 26. いい感じな例 (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 ... こっちは   プレゼンテーション寄り こっちは ビジネスロジック寄り  
  27. 27. モジュールのモック化 (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() 「ホホウ。もう出来てるじゃないか。じゃあ工数減ら して見積り再提出してもらえんかね」とお客様に言 われても当方は一切責任をもちません
  28. 28. おすすめツール •  wxPython Demo http://www.wxpython.org/download.php Demoを見れば大抵のウィジェットは使える •  Dash https://itunes.apple.com/jp/app/dash-docs- snippets/id458034879?mt=12 wxWidets のドキュメントがあります
  29. 29. enjoy!

×