Mais conteúdo relacionado
Semelhante a wxPython入門(大阪Pythonユーザの集まり2014/03) (20)
wxPython入門(大阪Pythonユーザの集まり2014/03)
- 2. 自己紹介
• 増田 泰 (@whosaysni)
• Google+ つかってません
• GitHub<<<BitBucket
• 某バイオベンチャー勤務
• ドキュメント翻訳とかDjango本とか
• 一般社団法人PyConJP理事
• PyConJPきてください 9/13-15
• http://2014.pycon.jp/
- 5. GUIプログラム
• シェルで起動
• 操作(イベント)に合わせてハ
ンドラが呼ばれる
• ハンドラがUIコンポーネントを
操作する
• 次のイベント待ち
GUIプログラミングって?
スクリプト
• シェルで起動
• 処理を逐次実行
• 最後の処理を終えたら終了
• シェルに制御を戻す
Webフレームワーク
• Webサーバが起動
• リクエストに合わせて
ハンドラが呼ばれる
• ハンドラがレスポンス返す
• 次のリクエスト待ち
ディス
パッチ
ハンドラ
ビュー
操作
イベント
ループ
- 6. ウィジェット Widget
• ボタンとかウィンドウとか、画面の構成要素
• UIを実際に描画する(自動的にね)
• ユーザ操作に応じてイベントを生成する
• wxPython/wxWidget
• ほとんどのウィジェットがクラスで階層化
wxObject
...
wxWindow
wxControl
wxBu4on
wxSta7cText
wxMenu
...
wxPanel
wxTopLevelWindow
wxFrame
wxDialog
- 7. イベントループ
while len(event_q):
ev = event_q.pop()
handler = dispatch(ev)
if handler:
handler(ev)
イベントキュー
イベントループロジック
GUI操作
その他
イベント
イベントハンドラ
イベントハンドラ
イベントハンドラ
たいていのGUIフレームワークには、
・イベントループを実行する関数
・ハンドラを登録する関数
があり、(1)ハンドラを定義して(2)ディ
スパッチャに登録し、(3)イベントルー
プを呼ぶようになっている。
- 8. wxPythonのイベントループ
>>> import wx
>>> app = wx.App() # Appインスタンス
>>> frame = wx.Frame(None) # ウィンドウつくる
>>> app.SetTopWindow(frame)
>>> frame.Show(True)
True
>>> app.MainLoop() # ここがメインループ
(ループ中。ウィンドウ閉じるまで戻りませんw)
- 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()
- 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
(上揃え)
- 18. イベントをハンドラに結びつける
ウィジェットの Bind() メソッドをつかう
例: widget.Bind(wx.EVT_MOUSE, handler)
• この操作で、
• 「widget」が
• 「マウスイベント」を受け取ると
• handler を呼び出す
• アプリのインスタンスメソッドの場合
• def handler(self, evt): ...
• self.bind(wx.EVT_MOUSE, self.handler)
- 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. いい感じな例
(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. いい感じな例
(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. モジュールのモック化
(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()
「ホホウ。もう出来てるじゃないか。じゃあ工数減ら
して見積り再提出してもらえんかね」とお客様に言
われても当方は一切責任をもちません