【问题标题】:Nested wxSizers; stacking panel vertically wrapping content嵌套的 wxSizer;堆叠面板垂直包装内容
【发布时间】:2021-08-13 16:53:00
【问题描述】:

这是我使用 HTML 和 CSS 创建的参考布局(颜色仅用于突出显示边界)。代码如下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .message {
                padding: 5px;
                background-color: red;
            }

            .text-field {
                margin: 0;
                padding: 5px;
                background-color: gray;
                color: black;
                display: inline-block;
            }

            .max-size {
                max-width: 60%;
            }

            .align-right {
                text-align: right;
            }

            .align-right p {
                text-align: left;
            }

        </style>
    </head>
    <body>
        <div class="message">
            <div class="msg-header">
                <p class="text-field max-size">Sender</p>
            </div>
            <div class="msg-content">
                <p class="text-field max-size">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
            </div>
        </div>
        <div class="message">
            <div class="msg-header align-right">
                <p class="text-field max-size">You</p>
            </div>
            <div class="msg-content align-right">
                <p class="text-field max-size">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
            </div>
        </div>
    </body>
</html>

我尝试使用 c++ 和 wxWidgets 实现相同的布局。忽略 60% 的最大尺寸,我尝试了以下操作。

MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, wxID_ANY, title, pos, size) {
    this->InitialiseComponents();
}

void MainFrame::InitialiseComponents() {
    ...

    this->panelChat = new wxScrolledWindow(this->splitterChatLog, MFID_LIST_BOX_CHAT, wxDefaultPosition, wxSize(850, 100));
    this->panelChat->SetBackgroundColour(wxColour(255, 255, 255));
    this->panelChat->SetScrollRate(5, 5);
    this->sizerChat = new wxBoxSizer(wxVERTICAL);
    this->panelChat->SetSizer(this->sizerChat);

    ...
}

void MainFrame::AddChatMessage(std::string addr, std::string str, bool sent) {
    wxPanel *panelMsg = new wxPanel(this->panelChat, wxID_ANY);
    panelMsg->SetBackgroundColour(wxColour(255, 0, 0));

    wxStaticText *textAddr = new wxStaticText(panelMsg, wxID_ANY, addr);
    wxStaticText *textMsg = new wxStaticText(panelMsg, wxID_ANY, str);

    wxBoxSizer *sizerMsgHeader = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *sizerMsgContent = new wxBoxSizer(wxVERTICAL);
    
    sizerMsgHeader->Add(textAddr, 0, (sent ? wxALIGN_RIGHT : 0));
    sizerMsgContent->Add(textMsg, 0, (sent ? wxALIGN_RIGHT : 0));

    wxBoxSizer *sizerMsg = new wxBoxSizer(wxVERTICAL);
    sizerMsg->Add(sizerMsgHeader, 0, wxEXPAND);
    sizerMsg->Add(sizerMsgContent, 0, wxEXPAND | wxBOTTOM, 5);
    panelMsg->SetSizer(sizerMsg);
    this->sizerChat->Add(panelMsg, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 5);
}

问题是:

  1. 多次调用 AddChatMessage 不会将它们叠加的消息堆叠起来。
  2. 每个消息面板都是一个 20x20 的红色正方形。它既不水平扩展也不包裹其内容。

【问题讨论】:

    标签: c++ wxwidgets


    【解决方案1】:

    我认为您只需要在 MainFrame::AddChatMessage 方法的末尾添加对 Layout();panelChat-&gt;Layout(); 的调用即可。这将强制 panelChat 窗口根据添加子项时赋予它的 sizer 标志重新排列其所有子项。

    不过,wxWidgets 确实提供了wxWebView 控件。如果您已经有一个 html 格式的聊天记录,那么使用该控件可能是显示它的最佳方式。


    您可以在聊天窗口的右侧或左侧将文本区域限制为 60%。一种方法是使用一个灵活的间隔设置来占据 40% 的宽度,并将消息面板设置为占据剩余的 60%。我认为这个版本的AddChatMessage 应该这样做。

    void MainFrame::AddChatMessage(std::string addr, std::string str, bool sent) {
        wxPanel *panelMsg = new wxPanel(this->panelChat, wxID_ANY);
        panelMsg->SetBackgroundColour(wxColour(255, 0, 0));
    
        wxStaticText *textAddr = new wxStaticText(panelMsg, wxID_ANY, addr);
        wxStaticText *textMsg = new wxStaticText(panelMsg, wxID_ANY, str);
        textMsg->Wrap(60 * GetClientSize().GetWidth() / 100);
    
        wxBoxSizer *sizerMsg = new wxBoxSizer(wxVERTICAL);
    
        sizerMsg->Add(textAddr, 0, (sent ? wxALIGN_RIGHT : 0));
        sizerMsg->Add(textMsg, 0, (sent ? wxALIGN_RIGHT : 0));
    
        panelMsg->SetSizer(sizerMsg);
    
        // Create a new horizontal sizer and add a spacer either before or after
        // taking up 40% of the horizontal space.
        wxBoxSizer* newChatSizer = new wxBoxSizer(wxHORIZONTAL);
        if ( sent )
        {
            newChatSizer->AddStretchSpacer(2);
        }
        newChatSizer->Add(panelMsg, 3, wxEXPAND);
        if ( !sent )
        {
            newChatSizer->AddStretchSpacer(2);
        }
        this->sizerChat->Add(newChatSizer, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 5);
    
        panelChat->Layout();
    }
    

    在这种情况下,这会添加一个比例为 2 的空格(左侧或右侧)。消息面板添加的比例为 3。由于总比例为 5,因此给定间隔 2/5 = 40% 的空间留下剩余 60% 的空间用于消息。

    注意:我还删除了 textAddrtextMsg 大小调整器,而是将静态文本添加到 sizerMsg。通常不需要只包含一个项目的sizer,而且我没有看到这两个sizer在做什么。

    【讨论】:

    • 好的,你知道如何使用 wxWidgets 实现 60% 的最大宽度吗?另外,我创建这个 HTML 示例只是为了了解结果的样子,因为我对 HTML 比 wxWidgets 更熟悉。没有我可以加载的实际聊天日志。如果可能的话,唯一的方法是将包含生成的 HTML 文档的字符串传递给 Web 视图。
    • 我尝试使用 resize 事件手动执行此操作,但是当我使用 Bind 添加此事件时,UI 变得不可见...
    • 评论编辑:panelChat 实际上是一个wxScrolledWindow,仅垂直。我不知道这是否会有所不同,但静态文本在超过 60% 时不会换行。甚至没有达到 100%。
    • 我认为您需要在静态文本上调用Wrap 方法才能将其换行。我已经编辑了答案以显示如何做到这一点。但是,设置后似乎无法更改换行,因此我认为如果您想在调整主窗体大小时重新换行,则需要使用 重新创建整个聊天,以便文本可以给定新的换行值。
    • 换行的问题是它没有显示属性,但它通过插入换行符改变了实际的数据集(标签)。因此,在收缩时调用 wrap 会通过再次插入换行符来再次更改标签,这会使标签越来越变形。增长时,换行不会改变任何内容,因为文本适合...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 2021-09-12
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多