スポンサーリンク

wxWidgetsのSizerを交換してレイアウトを変更する

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をクリア

// Sizerをクリア
currentSizer->Clear(false);

③ 新しいSizerを作成

// 新しい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をセット

// 親ウィジェットに新しい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);

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: