【问题标题】:C++ wxWidgets Sizer issue (beginner)C++ wxWidgets Sizer 问题(初学者)
【发布时间】:2020-08-11 19:31:19
【问题描述】:

我是 wxWidgets 和 sizer 的新手。我在框架构造函数中创建了以下结构

wxBoxSizer *frameSizer = new wxBoxSizer(wxHORIZONTAL);

wxBoxSizer *deckListLeftSizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *deckListRightSizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *logOutputSizer = new wxBoxSizer(wxVERTICAL);

// 10 inputs on left
for ( int i = 0; i < 10; i++ )
{
    wxTextCtrl *textCtrl = new wxTextCtrl(this, -1, wxT(""), wxPoint(-1, -1), wxSize(-1, -1));
    deckInputCastables.push_back(textCtrl);
    deckListLeftSizer->Add(textCtrl, wxEXPAND );
}

// 10 inputs on right
for ( int i = 0; i < 10; i++ )
{
    wxTextCtrl *textCtrl = new wxTextCtrl(this, -1, wxT(""), wxPoint(-1, -1), wxSize(-1, -1));
    deckInputLands.push_back(textCtrl);
    deckListRightSizer->Add(textCtrl, wxEXPAND );
}

logOutput = new wxStaticText(this, wxID_ANY, "Output Terminal", wxPoint(-1, -1), wxSize(-1, -1));
logOutput->SetBackgroundColour(*wxRED);
logOutputSizer->Add(logOutput);

frameSizer->Add(deckListLeftSizer, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5);
frameSizer->Add(deckListRightSizer, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5);
frameSizer->Add(logOutputSizer, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5);

frameSizer->Fit(this);
SetSizer(frameSizer);

这就是它的样子:

我想要的是蓝色的 StaticText 来填充它的整个大小,所以它占据了窗口的右侧 1/3,垂直和水平拉伸。此外,每个 TextCtrl 都垂直拉伸以填充其大小,但不是水平拉伸。当我调整框架大小时,我不想要任何未使用的空间,因此每个 textctrl 都会垂直和水平扩展。我做错了什么?

谢谢

【问题讨论】:

    标签: c++ wxwidgets


    【解决方案1】:

    @GeoffL,

    首先 - 没有 blue Static Text 只有 Red 一个。

    第二个——你可以看到的 wxALIGN_* 选项只在主要方向上起作用,即你传递给 wxBoxSizer() 构造函数的那个​​。

    你可能想要的是(未经测试):

    logOutput = new wxStaticText(this, wxID_ANY, "Output Terminal", wxPoint(-1, -1), wxSize(-1, -1));
    logOutput->SetBackgroundColour(*wxRED);
    logOutputSizer->Add(logOutput, 0, wxEXPAND | wxALIGN_CENTER_VERTICAL, 0 );
    

    wxEXPAND | wxALIGN_CENTER_VERTICAL 将扩展 sizer 并使控件垂直居中。

    您还可以在任何地方省略 wxALL 选项,因为它对存在的 wxALIGN 选项没有用。

    您也可以在控件构造函数中省略 wxPoint() 和 wxSize() 参数,因为 (-1, -1) 是默认值

    【讨论】:

    • 我认为你在正确的轨道上,但如果它被用作日志窗口,日志输出可能应该在展开后左上对齐——如果我理解这个问题的话。
    • @Igor 非常感谢您的回答。顺便说一句,如果你记得几天前我在使用 textctrls 时遇到了一个非常奇怪的错误,我通过使用 CodeBlocks 提供的 MinGW 来构建 wxWidgets 而不是我已经从某个地方拥有的 MinGW 来修复它。总之谢谢
    【解决方案2】:

    除了伊戈尔上面所说的,我还要补充两点。首先,在将项目添加到 sizer 时,我会使用wxSizerFlags。我认为这确实有助于澄清用于添加项目的所有数字和选项的作用。其次,通常只有一个项目的大小调整器(例如logOutputSizer)没有任何用途。我只想摆脱它。

    考虑到这两点,要回答你的问题,有必要使用比例参数和 Expand 方法来获取你想要的布局。例如:

    wxBoxSizer *frameSizer = new wxBoxSizer(wxHORIZONTAL);
    
    wxBoxSizer *deckListLeftSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *deckListRightSizer = new wxBoxSizer(wxVERTICAL);
    
    // 10 inputs on left
    for ( int i = 0; i < 10; i++ )
    {
        wxTextCtrl *textCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
        deckInputCastables.push_back(textCtrl);
        deckListLeftSizer->Add(textCtrl, wxSizerFlags(1).Expand());
    }
    
    // 10 inputs on right
    for ( int i = 0; i < 10; i++ )
    {
        wxTextCtrl *textCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
        deckInputLands.push_back(textCtrl);
        deckListRightSizer->Add(textCtrl, wxSizerFlags(1).Expand());
    }
    
    logOutput = new wxStaticText(this, wxID_ANY, "Output Terminal");
    logOutput->SetBackgroundColour(*wxRED);
    
    frameSizer->Add(deckListLeftSizer, wxSizerFlags(1).Expand());
    frameSizer->Add(deckListRightSizer, wxSizerFlags(1).Expand());
    frameSizer->Add(logOutput, wxSizerFlags(1).Expand());
    
    frameSizer->Fit(this);
    SetSizer(frameSizer);
    

    产生这个输出。

    这是一个开始,但它把所有东西都捆绑在一起,没有分离。要在项目之间添加一点分隔,您可以对 sizer 标志使用 Border 方法。但是,如果您只使用wxALL 为每个项目添加所有边框,您将获得多个双边框。例如,如果一个项目同时具有下边框,而其下方的项目具有上边框,则项目之间将有双边框。考虑到这一点,以下代码将在每个项目周围放置一个边框:

    wxBoxSizer *frameSizer = new wxBoxSizer(wxHORIZONTAL);
    
    wxBoxSizer *deckListLeftSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *deckListRightSizer = new wxBoxSizer(wxVERTICAL);
    
    // 10 inputs on left
    for ( int i = 0; i < 10; i++ )
    {
        wxTextCtrl *textCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
        deckInputCastables.push_back(textCtrl);
        deckListLeftSizer->Add(textCtrl, wxSizerFlags(1).Expand().Border(wxBOTTOM));
    }
    
    // 10 inputs on right
    for ( int i = 0; i < 10; i++ )
    {
        wxTextCtrl *textCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
        deckInputLands.push_back(textCtrl);
        deckListRightSizer->Add(textCtrl,  wxSizerFlags(1).Expand().Border(wxBOTTOM));
    }
    
    logOutput = new wxStaticText(this, wxID_ANY, "Output Terminal");
    logOutput->SetBackgroundColour(*wxRED);
    
    frameSizer->Add(deckListLeftSizer, wxSizerFlags(1).Expand().Border(wxTOP|wxLEFT|wxRIGHT));
    frameSizer->Add(deckListRightSizer, wxSizerFlags(1).Expand().Border(wxTOP|wxRIGHT));
    frameSizer->Add(logOutput, wxSizerFlags(1).Expand().Border(wxTOP|wxBOTTOM|wxRIGHT));
    
    frameSizer->Fit(this);
    SetSizer(frameSizer);
    

    这会产生这样的布局:

    有许多不同的方法可以重新排列边框选项以防止出现双边框,上面的示例只是一种可能性。

    最后,使用面板将框架中的所有项目分组通常是个好主意。它提供了更好看的背景,并允许您使用 Tab 键在控件之间移动。这是一个展示这个想法的最后一个例子:

    wxPanel* panel = new wxPanel(this,wxID_ANY);
    wxBoxSizer *panelSizer = new wxBoxSizer(wxHORIZONTAL);
    
    wxBoxSizer *deckListLeftSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *deckListRightSizer = new wxBoxSizer(wxVERTICAL);
    
    // 10 inputs on left
    for ( int i = 0; i < 10; i++ )
    {
        wxTextCtrl *textCtrl = new wxTextCtrl(panel, wxID_ANY, wxEmptyString);
        deckInputCastables.push_back(textCtrl);
        deckListLeftSizer->Add(textCtrl, wxSizerFlags(1).Expand().Border(wxBOTTOM));
    }
    
    // 10 inputs on right
    for ( int i = 0; i < 10; i++ )
    {
        wxTextCtrl *textCtrl = new wxTextCtrl(panel, wxID_ANY, wxEmptyString);
        deckInputLands.push_back(textCtrl);
        deckListRightSizer->Add(textCtrl,  wxSizerFlags(1).Expand().Border(wxBOTTOM));
    }
    
    logOutput = new wxStaticText(panel, wxID_ANY, "Output Terminal");
    logOutput->SetBackgroundColour(*wxRED);
    
    panelSizer->Add(deckListLeftSizer, wxSizerFlags(1).Expand().Border(wxTOP|wxLEFT|wxRIGHT));
    panelSizer->Add(deckListRightSizer, wxSizerFlags(1).Expand().Border(wxTOP|wxRIGHT));
    panelSizer->Add(logOutput, wxSizerFlags(1).Expand().Border(wxTOP|wxBOTTOM|wxRIGHT));
    
    panel->SetSizerAndFit(panelSizer);
    this->Fit();
    

    这会产生这样的布局:

    面板不需要使用大小调整器,因为当框架只有一个子级时,该子级会自动扩展以填充框架的所有空间。

    【讨论】:

    • 非常感谢,这是一个非常有用且简单的答案,我很感激,
    • @NewPagodi,感谢您涵盖所有这些要点。 ;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 2020-01-04
    • 2020-11-23
    • 2015-03-16
    • 2012-04-15
    相关资源
    最近更新 更多