wxPythonでダイアログ生成をするには
やりたいこと
wxPythonにてダイアログを生成したい。
画面作成にはwxGladeを利用する。
親画面作成
ダイアログを呼び出すボタンと、ダイアログに入力された値を受け取るテキストエリアを設ける。
#!/usr/bin/env python # -*- coding: UTF-8 -*- # # generated by wxGlade 0.9.9pre on Wed Oct 21 16:37:29 2020 # import wx # begin wxGlade: dependencies # end wxGlade # begin wxGlade: extracode import main_dialog # end wxGlade class MainPanel(wx.Panel): def __init__(self, *args, **kwds): # begin wxGlade: MainPanel.__init__ kwds["style"] = kwds.get("style", 0) wx.Panel.__init__(self, *args, **kwds) sizer = wx.BoxSizer(wx.VERTICAL) sizer_1 = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(sizer_1, 1, wx.EXPAND, 0) self.show_dialog_button = wx.Button(self, wx.ID_ANY, u"ダイアログ表示") self.show_dialog_button.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) sizer_1.Add(self.show_dialog_button, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) sizer_2 = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(sizer_2, 1, wx.EXPAND, 0) text = wx.StaticText(self, wx.ID_ANY, u"結果", style=wx.ALIGN_CENTER) text.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) sizer_2.Add(text, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) self.result_text = wx.StaticText(self, wx.ID_ANY, "") self.result_text.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) sizer_2.Add(self.result_text, 5, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) self.SetSizer(sizer) self.Layout() self.Bind(wx.EVT_BUTTON, self.show_dialog, self.show_dialog_button) # end wxGlade def show_dialog(self, event): # wxGlade: MainPanel.<event_handler> dialog = main_dialog.MainDialog(self, wx.ID_ANY, u'サンプル') result = dialog.ShowModal() if result == wx.ID_OK: self.result_text.SetLabel('入力内容:{}'.format(dialog.main_text.GetValue())) dialog.Destroy() # end of class MainPanel class MainFrame(wx.Frame): def __init__(self, *args, **kwds): # begin wxGlade: MainFrame.__init__ kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) self.SetSize((800, 300)) self.SetTitle(u"ダイアログテスト") self.main_panel = MainPanel(self, wx.ID_ANY) self.Layout() # end wxGlade # end of class MainFrame class MyApp(wx.App): def OnInit(self): self.main_frame = MainFrame(None, wx.ID_ANY, "") self.SetTopWindow(self.main_frame) self.main_frame.Show() return True # end of class MyApp if __name__ == "__main__": app = MyApp(0) app.MainLoop()
ダイアログの表示と後処理を実行しているのは以下の部分。
def show_dialog(self, event): # wxGlade: MainPanel.<event_handler> dialog = main_dialog.MainDialog(self, wx.ID_ANY, u'サンプル') result = dialog.ShowModal() if result == wx.ID_OK: self.result_text.SetLabel('入力内容:{}'.format(dialog.main_text.GetValue())) dialog.Destroy()
dialog.ShowModal()
をすることでダイアログを表示している。
また、ダイアログからの戻り値(wx.ID_OKやwx.ID_CANCEL)を受け取り、後処理(テキストエリアに結果を書き込む)を行う。
実際の画面イメージは以下の通り。
子画面作成
任意の文字を入力できるようにする。
「OK」ボタンを押下することで、入力した任意の文字を親画面に反映する。
「CANCEL」ボタンを押下すると何も反映しない。
#!/usr/bin/env python # -*- coding: UTF-8 -*- # # generated by wxGlade 0.9.9pre on Wed Oct 21 16:32:11 2020 # import wx # begin wxGlade: dependencies # end wxGlade # begin wxGlade: extracode # end wxGlade class MainDialog(wx.Dialog): def __init__(self, *args, **kwds): # begin wxGlade: MainDialog.__init__ kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE wx.Dialog.__init__(self, *args, **kwds) self.SetTitle(u"サンプル") sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_2 = wx.BoxSizer(wx.HORIZONTAL) sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) self.main_text = wx.TextCtrl(self, wx.ID_ANY, "") self.main_text.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) sizer_2.Add(self.main_text, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) sizer_3 = wx.BoxSizer(wx.HORIZONTAL) sizer_1.Add(sizer_3, 1, wx.EXPAND, 0) self.ok_button = wx.Button(self, wx.ID_OK, "OK") self.ok_button.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) sizer_3.Add(self.ok_button, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) self.cancel_button = wx.Button(self, wx.ID_CANCEL, "CANCEL") self.cancel_button.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) sizer_3.Add(self.cancel_button, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) self.SetSizer(sizer_1) sizer_1.Fit(self) self.Layout() # end wxGlade # end of class MainDialog class MyApp(wx.App): def OnInit(self): self.dialog = MainDialog(None, wx.ID_ANY, "") self.SetTopWindow(self.dialog) self.dialog.ShowModal() self.dialog.Destroy() return True # end of class MyApp if __name__ == "__main__": app = MyApp(0) app.MainLoop()
注意点としては、「OK」ボタンのIDをwx.ID_OK
にして、「CANCEL」ボタンのIDをwx.ID_CANCEL
にすること。
このIDをwx.ID_ANY
にするとダイアログは閉じない。
上記ソースにて、各ボタンの定義は以下のように記載している。
self.ok_button = wx.Button(self, wx.ID_OK, "OK")
self.cancel_button = wx.Button(self, wx.ID_CANCEL, "CANCEL")
実際の画面イメージは以下の通り。
注意点
ダイアログが閉じられた際の戻り値は各ボタンで設定したwx.ID_OK
(5100)やwx.ID_CANCEL
(5101)が格納される。
このとき、ダイアログを「×」ボタンで閉じた場合は戻り値として何が返却されるか?
常識的に考えればwx.ID_CANCEL
と同様に 5101 が返却されると考えるが、想定通りの動きとなるのか?
「OK」ボタンと「CANCEL」ボタンがそれぞれ存在する場合
上記で示した例で実践してもらえれば確認できる。
この場合では想定通りの戻り値を得ることができることが分かる。
「OK」ボタンだけが存在する場合
ダイアログに「OK」ボタンだけが存在する場合はどのような動作になるかを確認する。
具体的には子画面のソースが以下のような例で考える。
#!/usr/bin/env python # -*- coding: UTF-8 -*- # # generated by wxGlade 0.9.9pre on Wed Oct 21 18:37:50 2020 # import wx # begin wxGlade: dependencies # end wxGlade # begin wxGlade: extracode # end wxGlade class MainDialog(wx.Dialog): def __init__(self, *args, **kwds): # begin wxGlade: MainDialog.__init__ kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE wx.Dialog.__init__(self, *args, **kwds) self.SetTitle(u"サンプル") sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_2 = wx.BoxSizer(wx.HORIZONTAL) sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) self.main_text = wx.TextCtrl(self, wx.ID_ANY, "") self.main_text.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) sizer_2.Add(self.main_text, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) sizer_3 = wx.BoxSizer(wx.HORIZONTAL) sizer_1.Add(sizer_3, 1, wx.EXPAND, 0) self.ok_button = wx.Button(self, wx.ID_OK, "OK") self.ok_button.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) sizer_3.Add(self.ok_button, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) self.SetSizer(sizer_1) sizer_1.Fit(self) self.Layout() # end wxGlade # end of class MainDialog class MyApp(wx.App): def OnInit(self): self.dialog = MainDialog(None, wx.ID_ANY, "") self.SetTopWindow(self.dialog) self.dialog.ShowModal() self.dialog.Destroy() return True # end of class MyApp if __name__ == "__main__": app = MyApp(0) app.MainLoop()
実画面のイメージは以下の通り。
この状態でダイアログを「×」ボタンで閉じた場合は戻り値としてwx.ID_OK
と同じ5100を受け取る。
明確にキャンセルの処理を含めたいのであれば、明示的に「CANCEL」ボタンを作成する必要がある。