wxWidgetsでレイアウトを変更したい場合、
① 現在のSizerに登録されているウィジェットをバックアップ
② Sizerをクリアする(ただしそこに属しているウィジェットは削除しない)
③ 新しいSizerを作成
④ バックアップしたウィジェットを新しいSizerに設定
⑤ 新しいSizerをセット
wxWindowList windowList; wxSizerItemList& itemList = currentSizer->GetChildren(); // 現在のSizerからウィジェットを取り出してリストに保存 for (wxSizerItemList::iterator it = itemList.begin(); it != itemList.end(); ++it) { wxSizerItem* item = *it; if (item->IsWindow()) { wxWindow* window = item->GetWindow(); windowList.push_back(window); } }
// Sizerをクリア currentSizer->Clear(false);
// 新しいSizerを作成 wxBoxSizer* newSizer = new wxBoxSizer(wxVERTICAL);
// ウィジェットを新しいSizerに追加 for (wxWindowList::iterator it = windowList.begin(); it != windowList.end(); ++it) { wxWindow* window = *it; newSizer->Add(window, 1, wxALL | wxEXPAND, 0); }
// 親ウィジェットに新しいSizerを設定 panelB->SetSizer(newSizer);
// プリプロセッサに以下二つを追加 // __WXMSW__ // WXUSINGDLL // サブシステムをWindowsに設定(WinMainで呼び出すので) // Windows (/SUBSYSTEM:WINDOWS) #ifndef WX_PRECOMP #include <wx/wx.h> #endif #include <wx/gdicmn.h> // wxPointに必要 #include <wx/frame.h> // wxFrameに必要 ///////////////////////////////////// ///////////////////////////////////// ///////////////////////////////////// #include <string>
// ウィンドウ作成 class MyFrame : public wxFrame { public: wxBoxSizer* sizerB; wxPanel* panelB; void PanelAB() { // パネルA,B作成 // 交換ボタン配置用のパネル wxPanel* panelA = new wxPanel(this, wxID_ANY, wxPoint(0, 0), wxSize(200, 100)); panelA->SetBackgroundColour(wxColour(255, 0, 0)); // このパネルにパネルB1,B2を配置 // これらのレイアウトを変更する panelB = new wxPanel(this, wxID_ANY, wxPoint(200, 0), wxSize(200, 100)); panelB->SetBackgroundColour(wxColour(0, 0, 255)); // パネルAにボタン作成 wxButton* buttonA = new wxButton(panelA, wxID_ANY, "ButtonA", wxPoint(10, 10), wxSize(100, 50)); // 画面を上下に分割し、上にpanelA、下にpanelBを配置 wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(panelA, 0, wxEXPAND); sizer->Add(panelB, 1, wxEXPAND); SetSizer(sizer); // ボタンAを押したときのイベント buttonA->Bind(wxEVT_BUTTON, &MyFrame::OnButtonClicked, this); } void PanelB1B2() { // パネルBをsizerで左右に分割し、panelB1,panelB2を配置 sizerB = new wxBoxSizer(wxHORIZONTAL); wxPanel* panelB1 = new wxPanel(panelB, wxID_ANY, wxPoint(0, 0), wxSize(100, 100)); wxPanel* panelB2 = new wxPanel(panelB, wxID_ANY, wxPoint(0, 0), wxSize(100, 100)); panelB1->SetBackgroundColour(wxColour(255, 0, 255)); panelB2->SetBackgroundColour(wxColour(0, 255, 255)); sizerB->Add(panelB1, 1, wxEXPAND); sizerB->Add(panelB2, 1, wxEXPAND); panelB->SetSizer(sizerB); // パネルB1にボタン作成 wxButton* buttonB1 = new wxButton(panelB1, wxID_ANY, "ButtonB1", wxPoint(10, 10), wxSize(80, 50)); wxButton* buttonB2 = new wxButton(panelB2, wxID_ANY, "ButtonB2", wxPoint(10, 10), wxSize(80, 50)); } void PostCreate() { PanelAB(); PanelB1B2(); this->Layout(); // レイアウトの更新 }
// ボタンを押したときにSizerを交換 void OnButtonClicked(wxCommandEvent& event) { /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// wxBoxSizer* currentSizer = sizerB; if (currentSizer) { wxWindowList windowList;
wxSizerItemList& itemList = currentSizer->GetChildren(); // 現在のSizerからウィジェットを取り出してリストに保存 for (wxSizerItemList::iterator it = itemList.begin(); it != itemList.end(); ++it) { wxSizerItem* item = *it; if (item->IsWindow()) { wxWindow* window = item->GetWindow(); windowList.push_back(window); } }
// Sizerをクリア currentSizer->Clear(false);
// 新しいSizerを作成 wxBoxSizer* newSizer = new wxBoxSizer(wxVERTICAL);
// ウィジェットを新しいSizerに追加 for (wxWindowList::iterator it = windowList.begin(); it != windowList.end(); ++it) { wxWindow* window = *it; newSizer->Add(window, 1, wxALL | wxEXPAND, 0); }
// 親ウィジェットに新しいSizerを設定 panelB->SetSizer(newSizer);
this->Layout(); // レイアウトの更新 sizerB = newSizer; } }
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, wxID_ANY, title, pos, size) { // CallAfter : 現在処理中のイベントが終わったらPostCreateを実行 // コンストラクタはウィンドウ生成イベント扱い CallAfter(&MyFrame::PostCreate); } };
///////////////////////////////////// ///////////////////////////////////// ///////////////////////////////////// // wxWidgetsのアプリケーション作成 class MyApp : public wxApp { public: virtual bool OnInit() { MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340)); frame->Show(true); return true; } }; ///////////////////////////////////// ///////////////////////////////////// ///////////////////////////////////// // WinMainをマクロで定義 wxIMPLEMENT_APP(MyApp);