wxPythonでGUIレイアウトを作り込む時に参照するページ

  • このエントリーをはてなブックマークに追加

wxPython/wxFormBuilderを使ってGUIプログラミングを始めました。ここではウィンドウ処理やファイル処理をはじめとしたGUIプログラミングに必要となりそうな動作を一通り実装する方法を紹介します。目次から必要な項目が参照できます。

こんにちは。wat(@watlablog)です。ここではwxPythonによるGUIプログラミングの基礎を辞書的にまとめます

この記事の前提

wxFormBuilderを使っている

GUIプログラミングには色々な書き方があると思いますが、この記事ではwxFormBuilderを使って自動生成したクラスを編集するスタイルをとっています。

wxFormBuilderの詳細は「wxFormBuilderでwxPythonのGUIコード自動生成」に記載しています。

基本のPythonファイル

wxFormBuilderで自動生成した以下のファイルを前提として解説しますが、それぞれの動作実装コードはwxPythonを1から書いた場合でも参考できるものと思います。

MainClass.py

wxFormBuilderでfileを「MainClass」と設定して生成されるPythonファイル。基本このファイルはいじりません。

ProjectMainFrame.py

MainClassを継承し、FrameクラスをまとめたPythonファイルです。このファイルにイベントを設定します。

main.py

GUIクラスコードを呼びだすメインのPythonファイルです。exe化する時の対象でもあります。

それでは以下に各要素毎の動作実装方法をまとめます。

Frame全体に関するイベント

ウィンドウを閉じる

ウィンドウはそのままでも✖️印により閉じることができますが、うっかり押してしまった時のために一度メッセージダイアログを表示させた方が親切でしょう。

FrameのOnCloseにイベントを設定します。

wxFrame : https://wxpython.org/Phoenix/docs/html/wx.Frame.html

OnClose

イベント部に以下のコードを追記することで、Yes/Noボタンによるウィンドウクローズを実装します。

参考動作↓

タブを作る

タブはまずwxFormBuilderのContainers→wxNotebookで入れ物を作り、その後にContainers→wxPanelで任意数のパネルを追加して作ります。

wxNotebook : https://docs.wxpython.org/wx.Notebook.html

タブの作り方

wxNotebookだけではページ追加できないという仕様は以下の公式ディスカッションページが参考になりました。

i noticed that i can add a wxnotebook, but how can I add a page to this notebook. 

→You have to add a new wxPanel, each time you add a new wxPanel you will have a new tab in the wxNoteBook.

https://forums.wxwidgets.org/viewtopic.php?t=6822

Macだとこんな見栄えです↓

タブ見出しの位置はstyleで変更可能です(左とか右とか)。

style

ファイル操作に関するイベント

ファイルパスを取得する

ファイルパスはwxFilePickerを使います。同じような動作をするウィジェットは他にもwxdirPicker等があります。

wxfilePickerCtrl : https://wxpython.org/Phoenix/docs/html/wx.FilePickerCtrl.html

wxFilePickerはAdditionalにあります。

wxFilePickerの作り方

イベントはファイルパスが変化した時に設定します。

wxFilePickerのイベント設定

コード例はこちら。pathはオブジェクトの名前を指定して.GetPath()で取得できます。オブジェクト名はwxFormBuilderにも書いてありますが、MainClass.pyを参照しても良いでしょう。

動作例↓

ボタンからも同様のメソッドでパスを取得することができます。
以下の動画は直接wxFilePickerではなく、ボタンからパスを取得した例です。
取得したパスを静的テキストに書いたりしています。

パスを読めるようになったということで、csvやwavファイルといった外部ファイルをGUIから読みだすことができるようになったということですね。

フォルダ内の全ファイルをコンボボックスに設定する

次はコンボボックス(項目をリストから選択して値を取得するウィジェット)を使ってみます。コンボボックスは大変便利で、GUIプログラミングでよく使われます。

最も頻繁に使われる例としては、「フォルダ内のファイルを一括で設定し、後で選択できるようにする」といった操作ではないでしょうか。ここではフォルダを扱うwxdirPickerとコンボボックスwxComboBoxの2つを使って実装してみましょう。

wxComboBox : https://docs.wxpython.org/wx.ComboBox.html
wxdirPicker : https://docs.wxwidgets.org/3.0/classwx_dir_picker_ctrl.html

コンボボックスとディレクトリピッカーの配置

wxdirPickerはOnDirChangedにイベントを設定します。

wxdirPickerのイベント

wxComboBoxはOnComboBoxにイベント設定をすることで、プルダウンから項目を選択した時にイベントトリガーがかかります。

コンボボックスのイベント設定

今回はパスリストを保持するために、ProjectMainFrame.pyコンストラクタも編集しています。この書き方が良いかはわかりませんが、複数メソッドの中で共通の変数としたかったので…。

この辺は「Pythonのクラスの使い方とオブジェクト指向の考え方を理解する」で扱った内容なので、コンストラクタやメソッドについてはこちらの記事をご覧ください。

イベント部分のメソッドはこんな感じにしてみました。コンボボックスに最初に値を入れた時に、初回の処理を書いておくのが良いかも知れませんね(TODO部分)。好みだと思いますが。

以下動作例↓

matplotlibプロットに関するイベント

単純プロット

当ブログは数多くの記事でmatplotlibによるプロットを行っています。やはりGUIプログラミングでもmatplotlibを扱いたいと思います。

Tkinterでも「Tkinterでmatplotlibを埋め込んでグラフ表示する方法」で苦労しましたが、wxPython, さらにクラス表記の場合もひとクセありました。

今回は以下のページに記載のコードを参考にしました。https://gist.github.com/ikapper/765932799dd5dd36230b0d5205735bd3

ここでは少々やっかいなコードになりましたので、全コードをメモしておこうと思います。

MainClass.py

wxFormBuilderで生成したMainClass.pyは通常編集しませんが、wxFormBuilderでmatplotlibの設定がそのままあるわけではないので、今回は編集しました。

あらかじめwx.PanelをwxFormBuilderで配置させておき、bSizer1.Add()の部分でPanelの代わりに新しく作成したcanvasをSizerに追加しています。

まだこちらも仕組みがよく把握できていないので、この書き方で良いかは疑問…。

ProjectMainFrame.py

子フレームクラスをまとめたProjectMainFrame.pyにはイベントを設定しています。自分でdef plot()を作成し、ボタンイベントから呼び出して使うようにしてみました。

pop()remove()を使って毎回データを消去しているのがポイントです。これをやらないとボタンをクリックする度にプロットが増えます。色も毎回指定していますが…もっと良い書き方があるのかな?

main.py

main.pyはこれまでと変わりませんが、念のためメモ。

以上3つのファイルを使ってmain.pyを実行すると、以下の動画に示す動作が確認できます。

まとめ

今後も追記予定

今回はここまでですが、このページを見ればいつでもwxPythonとwxFormBuilderの使い方がわかるように今後も新しい機能を使う時があれば追記していこうと思います。

wxFormBuilderで大まかなフレームを作成し、その後にカスタマイズしていくというやり方は僕のようなGUIプログラミングライト層のスタイルに合っているようです。

1から組むのは面倒ですが、半分自動生成してくれるというのはかなり楽でした。

GUIプログラミングへの抵抗感が減ってきました!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメントを残す

*