突然ですが、Excelを使ったことはありますか?
圧倒的大多数の方はYESだと思います。
Excelの機能の一つに「検索」があります。
「Ctrl」 + 「F」キーでダイアログが表示されますね。
あのダイアログ、いくつも同時に表示することはできません。
でも表示させたままで他の作業をすることはできます。
よくよく考えたら不思議。
どうなっているんだろう?
今回はそんなお話です。
環境
- macOS Sierra 10.12.5
- python 3.4
- wxPython Phoenix 4.0.0
悪いスクリプト
まずは悪い見本のスクリプトを記述します。
# -*- coding: UTF-8 -*-
import wx
class App(wx.Frame):
""" GUI """
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(300, 300))
p = wx.Panel(self, wx.ID_ANY)
button = wx.Button(p, wx.ID_ANY, 'click')
button.Bind(wx.EVT_BUTTON, self.show_dialog)
layout = wx.BoxSizer(wx.VERTICAL)
layout.Add(button, flag=wx.ALL, border=10)
p.SetSizer(layout)
self.Show()
def show_dialog(self, event):
dialog = CustomDialog(self)
dialog.Show()
class CustomDialog(wx.Dialog):
""" カスタムダイアログ """
def __init__(self, parent):
wx.Dialog.__init__(self, parent, wx.ID_ANY, 'だいあろぐ', size=(150, 100))
p = wx.Panel(self, wx.ID_ANY)
label = wx.StaticText(p, wx.ID_ANY, 'さんぷる だいあろぐ')
layout = wx.BoxSizer(wx.VERTICAL)
layout.Add(label, flag=wx.ALL, border=10)
p.SetSizer(layout)
self.Centre()
app = wx.App()
App(None, wx.ID_ANY, 'タイトル')
app.MainLoop()
<実行結果>
解 説
悪いスクリプトでは、ボタンのクリックイベント内で別途作成したカスタムダイアログ・クラスを呼び出しています。
Excelの検索ダイアログのように、ダイアログを表示しながら他の作業ができるようにするにはモードレス表示にする必要がありますので「.ShowModal()」ではなく「.Show()」とする必要があります。
この場合、多重起動を制御する文を記述していませんので、ボタンをクリックする度にカスタムダイアログが表示されてしまいます。
良いスクリプト
# -*- coding: UTF-8 -*-
import wx
class App(wx.Frame):
""" GUI """
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(300, 300), style=wx.DEFAULT_FRAME_STYLE)
p = wx.Panel(self, wx.ID_ANY)
button = wx.Button(p, wx.ID_ANY, 'click')
button.Bind(wx.EVT_BUTTON, self.show_dialog)
layout = wx.BoxSizer(wx.VERTICAL)
layout.Add(button, flag=wx.ALL, border=10)
p.SetSizer(layout)
self.Show()
def show_dialog(self, event):
if self.FindWindowByName('だいあろぐ') is None:
dialog = CustomDialog(self)
dialog.Show()
else:
dialog = wx.MessageDialog(self, 'すでに表示されています', 'エラー', wx.ICON_ERROR)
dialog.ShowModal()
dialog.Destroy()
class CustomDialog(wx.Dialog):
""" カスタムダイアログ """
def __init__(self, parent):
wx.Dialog.__init__(self, parent, wx.ID_ANY, 'だいあろぐ', size=(150, 100))
p = wx.Panel(self, wx.ID_ANY)
label = wx.StaticText(p, wx.ID_ANY, 'さんぷる だいあろぐ')
layout = wx.BoxSizer(wx.VERTICAL)
layout.Add(label, flag=wx.ALL, border=10)
p.SetSizer(layout)
self.Centre()
app = wx.App()
App(None, wx.ID_ANY, 'タイトル')
app.MainLoop()
<実行結果> ↓ ↓ ↓