前回はウインドウにメニューとステータスバーを追加したが、今回はサブのウインドウを用意し、そこのボタンから、メインウインドウの状態をコントロールしてみる。以前にもサブウインドウからメインウインドウのコントロールを行ったが、その発展改良版でもある。前回のコードに追加・修正していくことにする。
まずは、サブウインドウを用意する。これは前回にはなかったものなので、新規で2つのファイルを用意することにする。
- controlpanel.hpp
#ifndef __CONTROLPANEL_HPP__ #define __CONTROLPANEL_HPP__ #include <wx/wx.h> const int ID_PLAY = 101; class ControlPanel : public wxFrame{ private: wxButton* button_; wxStaticText* text_; bool isPlay_; protected: public: ControlPanel(wxWindow* parent, const wxString& title, const wxPoint& pos, const wxSize& size); bool getPlayFlag(); void OnPlay(wxCommandEvent & event); }; #endif //CONTROLPANEL_HPP__
- conrtolpanel.cpp
#include "controlpanel.hpp" ControlPanel::ControlPanel(wxWindow* parent, const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(parent, wxID_ANY, title, pos, size), isPlay_(false) { wxPanel* panel = new wxPanel(this, wxID_ANY); this->button_ = new wxButton(panel, ID_PLAY, wxT("PLAY"), wxPoint(20, 20)); this->text_ = new wxStaticText(panel, wxID_ANY, wxT("Status : STOP"), wxPoint(20, 60)); Connect(ID_PLAY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ControlPanel::OnPlay)); } bool ControlPanel::getPlayFlag(){ return this->isPlay_; } void ControlPanel::OnPlay(wxCommandEvent & event) { if(this->isPlay_){ event.SetString(wxT("STOP")); this->text_->SetLabel(wxT("Status : STOP")); this->button_->SetLabel(wxT("PLAY")); this->isPlay_ = false; }else{ event.SetString(wxT("PLAY")); this->text_->SetLabel(wxT("Status : PLAY")); this->button_->SetLabel(wxT("STOP")); this->isPlay_ = true; } event.Skip(); }
ControlPanelクラスはwxFrameクラスの派生クラスで、ボタン(wxButton)とスタティックテキスト(wxStaticText)をメンバに持っている。また、イベントID「ID_PLAY」を定義し、対応するイベントハンドラのOnPlayメンバ関数を用意する。
ボタンやスタティックテキストなどのwidgetはwxPanelのインスタンスに配置していくことになる。Panelを用意しないと、ウインドウいっぱいの大きさになってしまったりするようだ。widgetのインスタンス生成は「親Widget、ID、ラベルテキスト、配置座標」を引数に渡して生成する。最後にID_PLAYとOnPlay、ボタンを紐づけを行っている。
OnPlayメンバ関数はメンバ変数「isPlay_」の状態に合わせて、ボタンとスタティックテキストのラベル文字列を変更している。また、受け取ったイベントに文字列を設定している。この文字列をメインウインドウ側で利用することになる。
関数の最後では、event.Skip()を実行しているが、これを実行するとイベントが親widgetへと伝播していく。これによって、メインウインドウにイベントを伝えている。
では、メインウインドウ側の変更点はどうなっているかというと、メインウインドウクラスにOnPlayメンバ関数を追加している。また、#include "controlpanel.hpp"も追加し、ControlPanelクラスを利用できるようにする。
- mainwindow.hpp
#include <wx/wx.h> #include <wx/menu.h> #include "controlpanel.hpp" class MainWindow : public wxFrame{ private: wxMenuBar* menubar_; wxMenu* menuFile_; wxMenu* menuHelp_; wxStatusBar* statusbar_; protected: public: MainWindow(const wxString& title, const wxPoint& pos, const wxSize& size); void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); void OnPlay(wxCommandEvent& event); // 追加 }; #endif //__MAINWINDOW_HPP__
コンストラクタ内でControlPanelクラスのインスタンスを作成して、イベントとの紐付けを行っている。
- MainWindow::MainWindow
MainWindow::MainWindow(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, wxID_ANY, title, pos, size) { /* 前回のコードと同じ ... */ //ここから--> this->Connect(ID_PLAY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainWindow::OnPlay)); ControlPanel* control = new ControlPanel(this, wxT("Control Panel"), wxPoint(650, 100), wxSize(300, 200)); control->Show(); //<--ここまで追加 }
ControlPanelクラスのインスタンスを作成し表示している。また、ControlPanelから伝播してくるであろうID_PLAYイベントとOnPlayイベントハンドラの関連づけも行っている。
- MainWindow::OnPlay
void MainWindow::OnPlay(wxCommandEvent & event) { this->statusbar_->SetStatusText(event.GetString()); }
OnPlayメンバ関数内ではステータスバーの表示を伝播してきたイベントの文字列に変更している。これで、ControlPanelないでボタンが押されると、「Play」または「STOP」とControlPanelのisPlay_変数の状態によって変化するはずである。
これらをビルドして実行すると次の動画のようになる。
意図したとおりになったようだ。
コメント