wxWidgets在程序创建后动态创建新的Sizer,而不是正确渲染新手

问题描述

我有以下GUI,该GUI是在当前位置使用空的sizer创建的。大小调整器可能是折叠的,因为它的比例为0,但是我这样画了它,所以您可以看到它。

enter image description here

当您单击“ + Need”按钮时,程序将创建带有一堆按钮和控件的新的定尺寸器,然后将其添加到该定尺寸器中。但是,它们没有出现在应有的位置。实际上,新的sizer及其内容已折叠,并且位于您的左上角

enter image description here

显然不是我想要的。但是,当我仅通过单击并拖动边缘之一来调整窗口大小时,所有内容都会弹出到位置:

enter image description here

我尝试调用我可以想到的-> Layout()和-> Fit()的每种组合,但我无法使其正常工作。这是在程序加载时创建GUI的代码,由框架构造函数调用。它创建“ needs_sizer_wrap”,它是BoxSizer,开始为空,单击按钮时将新的动态尺寸调整器添加到其中。注意,在图像中它显示为“ needsSizerWrap”,但代码实际上是“ needs_sizer_wrap”

// creates the basic GUI
void MullSimple_2Frame::createGUI()
{

    // mainPanel
    main_panel = new wxPanel(this,wxID_ANY);

    // mainPanelSizer (vertical)
    wxBoxSizer *main_panel_sizer = new wxBoxSizer(wxVERTICAL);

    // deckInfo (horizontal)
    // deck data along top like deck name,deck id,deck set
    wxBoxSizer *deck_info_sizer = new wxBoxSizer(wxHORIZONTAL);
    main_panel_sizer->Add(deck_info_sizer,wxSizerFlags(0).Expand());

        // DECK ID
        // label
        wxStaticText *label1 = new wxStaticText(main_panel,wxID_ANY,"DECK ID: ");
        deck_info_sizer->Add(label1,wxSizerFlags(0).Expand());

        // value
        deck_info_id = new wxStaticText(main_panel,"-1");
        deck_info_sizer->Add(deck_info_id,wxSizerFlags(0).Expand());

        // DECK NAME
        // label
        wxStaticText *label2 = new wxStaticText(main_panel,",NAME: ");
        deck_info_sizer->Add(label2,wxSizerFlags(0).Expand());

        // value
        deck_info_name = new wxTextCtrl(main_panel,"");
        deck_info_name->Bind(wxEVT_TEXT,&MullSimple_2Frame::ChangeDeckValue,this);
        deck_info_sizer->Add(deck_info_name,wxSizerFlags(0).Expand());

        // DECK SET
        // label
        wxStaticText *label3 = new wxStaticText(main_panel,SET: ");
        deck_info_sizer->Add(label3,wxSizerFlags(0).Expand());

        // value
        deck_info_set = new wxTextCtrl(main_panel,"");
        deck_info_set->Bind(wxEVT_TEXT,this);
        deck_info_sizer->Add(deck_info_set,wxSizerFlags(0).Expand());

        // DECK SAVED
        // can't do stuff unless the deck is saved. saving allows us to set data_vars.
        // label
        wxStaticText *label4 = new wxStaticText(main_panel,SAVED: ");
        deck_info_sizer->Add(label4,wxSizerFlags(0).Expand());

        // value
        deck_info_if_saved = new wxStaticText(main_panel,"FALSE");
        deck_info_sizer->Add(deck_info_if_saved,wxSizerFlags(0).Expand());



    // progSizer (horizontal)
    // program contains 3 "columns"
    wxBoxSizer *prog_sizer = new wxBoxSizer(wxHORIZONTAL);
    main_panel_sizer->Add(prog_sizer,wxSizerFlags(1).Expand());


    // PROGRAM COLUMN 1: DECK CASTABLES

    // castables column
    wxBoxSizer *deck_casts_sizer = new wxBoxSizer(wxVERTICAL);
    prog_sizer->Add(deck_casts_sizer,wxSizerFlags(1).Expand());

    // castables title
    wxStaticText *deck_casts_title = new wxStaticText(main_panel,"Castables",wxDefaultPosition,wxSize(-1,30),wxALIGN_CENTER_HORIZONTAL);
    deck_casts_title->SetBackgroundColour(*wxYELLOW);
    deck_casts_sizer->Add(deck_casts_title,wxSizerFlags(0).Expand());

    // castables content
    for ( int i = 0; i < 25; i++ )
    {
        // need to set a size so that they're small enough to all fit on my crappy laptio
        wxTextCtrl *text_ctrl = new wxTextCtrl(main_panel,wxEmptyString,20));
        text_ctrl->Bind(wxEVT_TEXT,this);
        deck_castable_inputs.push_back(text_ctrl);
        deck_casts_sizer->Add(text_ctrl,wxSizerFlags(0).Expand());
    }


    // PROGRAM COLUMN 2: DECK LANDS

    wxBoxSizer *deck_lands_sizer = new wxBoxSizer(wxVERTICAL);
    prog_sizer->Add(deck_lands_sizer,wxSizerFlags(1).Expand());

    // lands title
    wxStaticText *deck_lands_title = new wxStaticText(main_panel,"Lands",wxALIGN_CENTER_HORIZONTAL);
    deck_lands_title->SetBackgroundColour(*wxGREEN);
    deck_lands_sizer->Add(deck_lands_title,wxSizerFlags(0).Expand());

    // lands content
    for ( int i = 0; i < 25; i++ )
    {
        wxTextCtrl *text_ctrl = new wxTextCtrl(main_panel,this);
        deck_land_inputs.push_back(text_ctrl);
        deck_lands_sizer->Add(text_ctrl,wxSizerFlags(0).Expand());
    }


    // PROGRAM COLUMN 3: HAND

    wxBoxSizer *hand_sizer = new wxBoxSizer(wxVERTICAL);
    prog_sizer->Add(hand_sizer,wxSizerFlags(1).Expand());

    // hand title
    wxStaticText *hand_title = new wxStaticText(main_panel,"Hand",wxALIGN_CENTER_HORIZONTAL);
    hand_title->SetBackgroundColour(*wxBLUE);
    hand_sizer->Add(hand_title,wxSizerFlags(0).Expand());

    // hand content
    for ( int i = 0; i < 7; i++ )
    {
        wxTextCtrl *text_ctrl = new wxTextCtrl(main_panel,20));
        hand_inputs.push_back(text_ctrl);
        hand_sizer->Add(text_ctrl,wxSizerFlags(0).Expand());
    }


    // PROGRAM COLUMN 4: MULL OPTS

    wxBoxSizer *mull_opts_sizer = new wxBoxSizer(wxVERTICAL);
    prog_sizer->Add(mull_opts_sizer,wxSizerFlags(3).Expand());

    // MULL OPTS HORIZONTAL 1: MULL_OPTS_BUTTONS

    wxBoxSizer *mull_opts_but_sizer = new wxBoxSizer(wxHORIZONTAL);
    mull_opts_sizer->Add(mull_opts_but_sizer,wxSizerFlags(0).Expand());

        // add need button
        mull_opts_but_add_need = new wxButton(main_panel,"+ Need");
        mull_opts_but_add_need->SetMinSize(wxSize(-1,50));
        mull_opts_but_add_need->Bind(wxEVT_BUTTON,&MullSimple_2Frame::addNeedGlobal,this);
        mull_opts_but_sizer->Add(mull_opts_but_add_need,wxSizerFlags(1).Expand());

        // remove need button
        mull_opts_but_remove_need = new wxButton(main_panel,"- Need");
        mull_opts_but_remove_need->SetMinSize(wxSize(-1,50));
        mull_opts_but_remove_need->Bind(wxEVT_BUTTON,&MullSimple_2Frame::removeNeedGlobal,this);
        mull_opts_but_sizer->Add(mull_opts_but_remove_need,wxSizerFlags(1).Expand());

        // reset all button
        mull_opts_but_reset_needs = new wxButton(main_panel,"Reset All");
        mull_opts_but_reset_needs->SetMinSize(wxSize(-1,50));
        mull_opts_but_reset_needs->Bind(wxEVT_BUTTON,&MullSimple_2Frame::resetNeedsGlobal,this);
        mull_opts_but_sizer->Add(mull_opts_but_reset_needs,wxSizerFlags(1).Expand());

        // calculate button
        mull_opts_but_calculate = new wxButton(main_panel,"Calculate");
        mull_opts_but_calculate->SetMinSize(wxSize(-1,50));
        mull_opts_but_calculate->Bind(wxEVT_BUTTON,&MullSimple_2Frame::calcNeedsGlobal,this);
        mull_opts_but_sizer->Add(mull_opts_but_calculate,wxSizerFlags(1).Expand());

    // needs sizer wrap,contains the needs,starts out empty
    needs_sizer_wrap = new wxBoxSizer(wxVERTICAL);
    mull_opts_sizer->Add(needs_sizer_wrap,wxSizerFlags(0).Expand());

    // MULL OPTS HORIZONTAL 2: NEEDS (in a stack)
    // Make on base need we can use as a model


    // at the bottom of the main panel stretches the log output
    // fixed height so set proportion 0
    wxBoxSizer *output_sizer = new wxBoxSizer(wxHORIZONTAL);
    main_panel_sizer ->Add(output_sizer,wxSizerFlags(0).Expand());

    log_output = new wxTextCtrl(main_panel,100),wxTE_MULTILINE);
    log_output->SetBackgroundColour(*wxYELLOW);
    output_sizer ->Add(log_output,wxSizerFlags(1).Expand());



    main_panel->SetSizerAndFit(main_panel_sizer);
    this->Fit();

}

这是单击+需求按钮时插入附加的sizer的代码

void MullSimple_2Frame::addNeedGUI()
{

    wxBoxSizer *need_sizer = new wxBoxSizer(wxVERTICAL);

    // NEED ITEM HORIZONTAL 1: grid of filters,4 columns

    // we'll put the same filters for every deck (for Now),// and no custom filter ability
    std::vector<std::string> filters_in_deck;
    filters_in_deck.push_back("Land");
    ...

    // fixed 2 rows with 4 cols in each row
    wxGridSizer *base_need_filters_sizer = new wxGridSizer(2,4,0);
    need_sizer->Add(base_need_filters_sizer,wxSizerFlags(0).Expand());

    for ( unsigned int i = 0; i < filters_in_deck.size(); i++ )
    {
        wxCheckBox *filter_check = new wxCheckBox(this->main_panel,myHelpFxns::ToWxString(filters_in_deck[i]));
        base_need_filters_sizer->Add(filter_check,wxSizerFlags(1).Expand());
    }

    // NEED ITEM HORIZONTAL 2: line options

    wxBoxSizer *base_need_line_sizer = new wxBoxSizer(wxHORIZONTAL);
    need_sizer->Add(base_need_line_sizer,wxSizerFlags(0).Expand());

    // line item -> "("
    wxButton *need_line_open_brack_but = new wxButton(this->main_panel,"(",wxSize(50,-1));

    base_need_line_sizer->Add(need_line_open_brack_but,wxSizerFlags(0).Expand());

    // line item -> apply filters logic (any/all)
    wxComboBox *need_line_apply_filters_combo = new wxComboBox(this->main_panel,wxID_ANY);
    need_line_apply_filters_combo->Append("Any");
    need_line_apply_filters_combo->Append("All");
    base_need_line_sizer->Add(need_line_apply_filters_combo,wxSizerFlags(1).Expand());

    // line item -> cards to draw combo Box
    wxComboBox *need_line_cards_draw_combo = new wxComboBox(this->main_panel,wxID_ANY);
    need_line_cards_draw_combo->Append("1 to Draw");
    ...
    base_need_line_sizer->Add(need_line_cards_draw_combo,wxSizerFlags(1).Expand());

    // line item -> source colors combo
    wxComboBox *need_line_source_colors_combo = new wxComboBox(this->main_panel,wxID_ANY);
    need_line_source_colors_combo->Append("Any");
    ...
    base_need_line_sizer->Add(need_line_source_colors_combo,wxSizerFlags(1).Expand());

    // line item -> cost colors combo
    wxComboBox *need_line_cost_colors_combo = new wxComboBox(this->main_panel,wxID_ANY);
    need_line_cost_colors_combo->Append("Any");
    ...
    base_need_line_sizer->Add(need_line_cost_colors_combo,wxSizerFlags(1).Expand());

    // line item -> cost amount combo
    wxComboBox *need_line_cost_amount_combo = new wxComboBox(this->main_panel,wxID_ANY);
    need_line_cost_amount_combo->Append("Any");
    ...
    base_need_line_sizer->Add(need_line_cost_amount_combo,wxSizerFlags(1).Expand());

    // line item -> specific card input
    wxTextCtrl *need_line_specific_card_input = new wxTextCtrl(this->main_panel,wxEmptyString);
    base_need_line_sizer->Add(need_line_specific_card_input,wxSizerFlags(1).Expand());

    // line item -> ")"
    wxButton *need_line_close_brack_but = new wxButton(this->main_panel,")",-1));
    base_need_line_sizer->Add(need_line_close_brack_but,wxSizerFlags(0).Expand());

    // line item -> "AND"
    wxButton *need_line_and_but = new wxButton(this->main_panel,"AND",-1));
    base_need_line_sizer->Add(need_line_and_but,wxSizerFlags(0).Expand());

    // line item -> "OR"
    wxButton *need_line_or_but = new wxButton(this->main_panel,"OR",-1));
    base_need_line_sizer->Add(need_line_or_but,wxSizerFlags(0).Expand());

    // NEED ITEM HORIZONTAL 3: NEED INLINE BUTTONS

    wxBoxSizer *base_need_buts_sizer = new wxBoxSizer(wxHORIZONTAL);
    need_sizer->Add(base_need_buts_sizer,wxSizerFlags(0).Expand());

    wxButton *need_but_add_need_after_but = new wxButton(this->main_panel,"+");
    base_need_buts_sizer->Add(need_but_add_need_after_but,wxSizerFlags(0).Expand());

    wxButton *need_but_remove_this_but = new wxButton(this->main_panel,"-");
    base_need_buts_sizer->Add(need_but_remove_this_but,wxSizerFlags(0).Expand());

    needs_sizer_wrap->Add(need_sizer,wxSizerFlags(0).Expand().Border(wxALL,10));
    //needs_sizer_wrap->Layout();
    //needs_sizer_wrap->Fit(need_sizer);
}

解决方法

直到现在我才意识到这一点,但是根据文档,当您在top level window上调用Layout

时,

使用窗口大小调整器布置子项或调整唯一子项的大小 覆盖整个窗口的面积。

此类重写基类Layout()方法以检查是否 窗口中恰好包含一个孩子-通常是这样, wxPanel通常被创建为wxTopLevelWindow的唯一子项– 如果是这种情况,请调整此子窗口的大小以覆盖 整个客户区。

所以我猜想在只有1个子窗口的框架上调用Layout是行不通的,因为该调用只会尝试调整面板的大小,但是面板不会更改尺寸,因此不会尝试重新布局其新的子窗口

似乎起作用的是添加类似的内容

this->main_panel->Layout();

MullSimple_2Frame::addNeedGUI()的末尾。这样会在面板上而不是框架上重新布局。

或者,根据文档,您可以仅使用调整大小的框架,并仅向其添加main_panel。但是,正如我在另一个答案中所说的那样,通常只有一个窗口的尺寸调整器没有多大意义。