6. ファイルメニュー機能をつける
次にやるべきことは、メニュー機能の実装とユーザーとを相互に作用させることです。ダイアログはユーザーからの入力を直接受け取るために使われます。ダイアログはモーダルアプリケーション、すなわちダイアログが閉じるまで現在のアプリケーション上の他のウィンドウを使うことができないものです。
- ダイアログは直接ソースコードに書き込みます。デザイナ上で配置できません。エディタを使って配置します。ソースコードwxFrame1タブ内のExploreタブというオブジェクト一覧が表示されたタブがありますのでそれを開きます(wxFrame1内のヤツです。Explorerタブではありません)。wxFrame1を展開し、OnMnufileitems0Menu(=mnuFileの1番目のアイテム)をダブルクリックしてください。ソースコード上のOnFileitems0Menuに移動します。このメソッド内にカーソルを置いて、「ファイルを開く(File Open)」ダイアログを配置します。
- パレット上でDialogsタブを選択してください。wxFileDialogボタンを選択します。wxFileDialogボタンを押すと、Boa Constructorはイベントハンドラメソッドに直接スケルトンコードを貼り付けます。スケルトンコードは以下の通りです。
def OnMnufileitems0Menu(self, event):
dlg = wxFileDialog(self, "Choose a file", ".", "", "*.*", wxOPEN)
try:
if dlg.ShowModal() == wxID_OK:
filename = dlg.GetPath()
# Your code
finally:
dlg.Destroy()
event.Skip()
- スケルトンコードはダイアログを作成します。これはユーザーと相互に作用します。ダイアログは終了されたときに破棄されます。
- 「# Your code」は作成しているコードを挿入する場所ですよ、と目印をつけています。この直後に書き込んだコードはユーザーがファイル名を選択もしくは入力したときにのみ呼び出されます。ここに作成するコードを挿入することにしましょう。wxTextCtrlは、ファイルをエディットウィンドウにロードするために使うメソッドを持っています。そのメソッドは「LoadFile」です。
- もし必要ならば、最後の「event.Skip()」を削除することができます。今回はこのevent.Skip()は必要はありません。削除しましょう。ただ、デザイナ上でコードが生成された時は必要になります。なぜなら、メソッド内に何も記述されていない場合、pythonはそれを報告しエラーを出すからです。
- アプリケーションの機能上、ファイルを開く時に、開いたファイル名を変数に保存する必要があります。ここではself.FileNameという変数を作成します。以下は作成するコードを表します。
def OnMnufileitems0Menu(self, event):
dlg = wxFileDialog(self, "Choose a file", ".", "", "*.*", wxOPEN)
try:
if dlg.ShowModal() == wxID_OK:
filename = dlg.GetPath()
self.txtEditor.LoadFile(filename)
self.FileName=filename
finally:
dlg.Destroy()
#注:windows環境でうまく読み込めない人はself.txtEditor.LoadFile(filename)を
self.txtEditor.SetValue(open(filename, 'r').read().decode("mbcs"))
に変えてみてください。どちらにせよ、ファイル名に日本語をつけるとファイルを見つけてくれません。
- 「Save As」機能を提供するため、今やったことを繰り返す必要があります。Save As メニューアイテムはitem2です。さっきと同じようにExploreタブのOnMnufileimtes2Menuダブルクリックし、ファイルダイアログをOnFileitems2Menuのボディに挿入して下さい。これはFileSaveダイアログです。プロンプトを変更し、wxFileDialogの2番目のパラメータを「Save File As」に変えます。スタイルを変えるため、6番目のパラメータををwxSAVEに変えます。ファイルを保存するメソッドにはSaveFileを呼び出します。
- 繰り返しますが、「Save」メニューオプションを使うためにファイル名の値を保存します。以下にそのコードを示します(注:私の環境では日本語の文字列は保存されませんでした・・・。SaveFile使わずファイルをOpenして書き込めば保存は可能だと思います。)。
def OnMnufileitems2Menu(self, event):
dlg = wxFileDialog(self, "Save File As", ".", "", "*.*", wxSAVE)
try:
if dlg.ShowModal() == wxID_OK:
filename = dlg.GetPath()
self.txtEditor.SaveFile(filename)
self.FileName=filename
finally:
dlg.Destroy()
- 次に「Close」メニューオプションを実装しましょう。このメソッドにおいては、単にテキストエディタスクリーンフィールドとファイル名のメンバ変数をまっさらにするだけです。
def OnMnufileitems3Menu(self, event):
self.FileName = None
self.txtEditor.Clear()
- 次は「Exit」メニューオプションを実装します。このメリットでは、アプリケーションを終了する必要があります。すべてのwxPythonアプリケーションはトップレベルウィンドウを閉じることにより終了します。今回のケースでは、wxFrame1ウィンドウを閉じるだけです。アプリケーションを終了するには、wxFrame1にClose()メソッドを呼び出します。
def OnMnufileitems4Menu(self, event):
self.Close()
- 次にSaveメニューアイテムを実装します。このメニューアイテムは現在の名前(self.FileName変数に収められています)を使ってファイルを保存します。
- 現在のファイルがない場合、self.FileName変数はNoneにセットされます。この場合「Save」メニューオプションは「Save As」メニューオプションのようにふるまう必要があります。
- wxFrameが作られたときにFilename変数が作られる必要があります。コンストラクタにそれを追加しなければいけません。デフォルトコンストラクタ(__init__)の終わりにアプリケーションのコードを追加することができます。
- 今までと同じように、wxFrame1タブ内のExploreタブ上から__init__をダブルクリックして以下を記述します。
def __init__(self, parent):
self._init_ctrls(parent)
self.FileName=None
- ここで安全にSave機能を実装しましょう。現在のファイル名があるかどうかチェックします。もしある場合はそのファイル名で内容を保存します。そうではない場合「Save As」メソッドを呼び出す必要があります。
def OnMnufileitems1Menu(self, event):
if self.FileName == None:
return self.OnMnufileitems2Menu(event)
else:
self.txtEditor.SaveFile(self.FileName)
- これでエディタの機能を実装したわけです。ファイルを編集して保存することができます。作成したエディタは以下のようになるはずです。