当其容器面板或框架变小,wxListBox停止使用水平滚动条并扩展占用过多空间

2 投票
2 回答
960 浏览
提问于 2025-04-17 09:58

SSCCE 在底部

我的布局有两个 wx.ListBox,并排放在一个 wx.FlexGridSizer 中:

到目前为止还不错

我的实际布局更复杂,所以用了 FGS,但这个小例子依然能展示出问题。

如上所示,我成功地使用了 style = wx.LB_HSCROLL,让每个列表框在内容超出 wx.Frame 的时候显示水平滚动条。

然而,当我把窗口缩得越来越小时,最终会达到一个临界点,第一个列表框决定不再使用滚动条,而是扩展到它的最大尺寸,把第二个列表框推到右边:

窗口变得太小了!

列表框失控的那个点取决于字符串的长度。如果我在第一个框中放入一个足够长的字符串,那么上述过程就会反转:布局一开始就错了,我必须把窗口的大小调大到临界点,然后列表框突然开始使用滚动条,变得小很多,窗口就会像应该的那样被分成两半。

我不确定这是不是 wxWidgets/wxPython 的一个bug,还是我做错了什么,但无论如何这都让我很沮丧。以下是我能想到的最简单的代码,能展示这个问题:

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent = None, size = (640, 480))

        self.list1 = wx.ListBox(self, style = wx.LB_HSCROLL)
        self.list2 = wx.ListBox(self, style = wx.LB_HSCROLL)

        self.list1.Append('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
        self.list2.Append('bbbbbbbbbbb')

        self.fgs = wx.FlexGridSizer(1, 2)
        self.fgs.AddMany([(self.list1, 1, wx.EXPAND), (self.list2, 1, wx.EXPAND)])
        self.fgs.AddGrowableRow(0, 1)
        self.fgs.AddGrowableCol(0, 1)
        self.fgs.AddGrowableCol(1, 1)

        self.Bind(wx.EVT_SIZE, self.OnSize)

        self.Sizer = fgs
        self.Layout()
        self.Show()

    def Exit(self, event):
        self.Close(True)

app = wx.App(False)
frame = MyFrame()
app.MainLoop()

编辑:这是我用 Python 实现 ravenspoint 代码的版本(上面的代码稍微改动了一下以支持这个):

def OnSize(self, event):
    if not self.list1 or not self.list2;
        return

    clientRect = self.GetClientRect()
    min = wx.Size(clientRect.width / 2, clientRect.height)

    self.list1.MinSize = min
    self.list2.MinSize = min

2 个回答

1

因为我也遇到过这个问题,所以我把这个分享出来,方便以后参考。至少在使用wxPython的时候,你必须指定一个最小大小,否则它会自动选择一个最佳大小(至少对于列表框来说),这样可能会导致布局管理器把一些控件挤到当前窗口的外面。因此,为了让上面的代码正常工作,需要添加的代码是:

    self.list1.SetMinSize((10,10));
    self.list2.SetMinSize((10,10));

完整的解决方案是:

import wx
class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent = None, size = (640, 480))

        self.list1 = wx.ListBox(self, style = wx.LB_HSCROLL)
        self.list2 = wx.ListBox(self, style = wx.LB_HSCROLL)

        self.list1.Append('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
        self.list2.Append('bbbbbbbbbbb')

        self.fgs = wx.FlexGridSizer(1, 2)
        self.fgs.AddMany([(self.list1, 1, wx.EXPAND), (self.list2, 1, wx.EXPAND)])
        self.fgs.AddGrowableRow(0, 1)
        self.fgs.AddGrowableCol(0, 1)
        self.fgs.AddGrowableCol(1, 1)

        # Don't forget these two lines to allow for correct 
        # expansion/contraction of the sizer!
        self.list1.SetMinSize((10,10));
        self.list2.SetMinSize((10,10));

        self.Sizer = self.fgs
        self.Layout()
        self.Show()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()
1

你可能需要自己处理窗口大小改变的事件。在C++中,处理这个事件的代码大概是这样的:

void MyFrame::OnSize(wxSizeEvent& )
{
    if( ! ( list1 && list2 ) )
        return;
    wxRect frame_client = GetClientRect();
    wxSize min(frame_client.width/2,frame_client.height );
    list1->SetMinSize(min);
    list2->SetMinSize(min);
    fgs->Layout();
}

撰写回答