wxpython 如何在调整 window 大小时防止 BoxSizer 折叠?

wxpython How to prevent BoxSizer from collapsing when window is resized?

我正在使用 BoxSizer 作为水平和垂直布局。但是,当我在水平 BoxSizer 中使用垂直 BoxSizer 来包含我的按钮时,它会垂直显示在另一个元素旁边,并且当您调整它的大小时,它会折叠并隐藏按钮,直到您再次展开它。

这是默认情况下的样子

这是我们将其调整为更小宽度后的样子

如您所见,按钮在调整大小时折叠起来。如何在 window 调整大小时阻止 BoxSizer 折叠?

Code

sizer 只是使用可用大小来布置元素。如果不够,则 sizer 别无选择,只能截断(甚至完全隐藏)一些项目。

为确保不会发生这种情况,您必须确保 window 不能小于其最小尺寸。这是通过 SetMinClientSize() 完成的,它由方便的 SetSizerAndFit() 包装器调用,您的代码中都没有使用它们。

首先,在问题中而不是在 link 上发布您的代码的半严格规则是为了让人们可以看到您是否更改了它,您已经更改了!

您的代码现已更改,因此很难解释对原始代码所做的更改以及它们与新代码的关系。

基本上,在使用 sizer 时,您必须特别注意比例和 wx.EXPAND 标志。它们会导致各种意想不到的后果。

就我个人而言,我可能会 运行 使用不同的 sizer,也许 FlexGridSizer 为此。

这是您的原始代码,proportion 和扩展 flags 已调整为执行我假设您想要的。

import wx
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin

#from processor import process_xls

class MainFrame(wx.Frame):

    TITLE = 'Neko'
    FRAME_MIN_SIZE = (600, 300)
    DEFAULT_BORDER_SIZE = 10

    INPUT_LABEL = 'Input files : '
    ADD_LABEL = 'Add'

    REMOVE_LABEL = 'Remove'
    START_LABEL = 'Start'

    FILE_LABEL = 'File'
    SIZE_LABEL = 'Size'
    PERCENT_LABEL = 'Percent'
    ETA_LABEL = 'ETA'
    SPEED_LABEL = 'Speed'
    STATUS_LABEL = 'Status'
    STATUS_LIST = {
        'filename': (0, FILE_LABEL, 120, True),
        'size': (1, SIZE_LABEL, 60, False),
        'percent': (2, PERCENT_LABEL, 80, False),
        'eta': (3, ETA_LABEL, 60, False),
        'speed': (4, SPEED_LABEL, 60, False),
        'status': (5, STATUS_LABEL, 90, False),
    }

    def __init__(self, *args, **kwargs):
        super(MainFrame, self).__init__(*args, **kwargs)

        self.SetTitle(self.TITLE)
        self.SetSize(self.FRAME_MIN_SIZE)

        self._panel = wx.Panel(self)
        self._vertical_box = wx.BoxSizer(wx.VERTICAL)

        # Inputs
        self._horizontal_box_input = wx.BoxSizer(wx.HORIZONTAL)

        self._tc_file_picker = wx.TextCtrl(self._panel)
        self._horizontal_box_input.Add(self._tc_file_picker,
                                    proportion=1, flag=wx.EXPAND)

        self._button_add = wx.Button(self._panel,
                                label=self.ADD_LABEL,
                                size=(-1,-1))
        self._button_add.Bind(wx.EVT_BUTTON,
                            self._on_add)
        self._horizontal_box_input.Add(self._button_add,
                                    flag=wx.LEFT,
                                    border=self.DEFAULT_BORDER_SIZE)

        self._vertical_box.Add(self._horizontal_box_input,
                            flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP,
                            border=self.DEFAULT_BORDER_SIZE)

        # Status List
        self._status_list = ListCtrl(self.STATUS_LIST,
                                parent=self._panel,
                                style=wx.LC_REPORT | wx.LEFT | wx.RIGHT)
        self._horizontal_box_status_list = wx.BoxSizer(wx.HORIZONTAL)
        self._horizontal_box_status_list.Add(self._status_list,
                                        proportion=1, flag=wx.EXPAND)

        status_list_buttons_data = {
            ('remove', self.REMOVE_LABEL, (-1, -1), self._on_remove, wx.Button),
            ('start', self.START_LABEL, (-1, -1), self._on_start, wx.Button),
        }

        # Create buttons vertically
        self._vertical_control_box = wx.BoxSizer(wx.VERTICAL)
        for item in status_list_buttons_data:
            name, label, size, evt_handler, parent = item

            button = parent(self._panel, size=size)

            if parent == wx.Button:
                button.SetLabel(label)

            if evt_handler is not None:
                button.Bind(wx.EVT_BUTTON, evt_handler)

            self._vertical_control_box.Add(button,
                                        flag=wx.LEFT|wx.BOTTOM|wx.EXPAND,
                                        proportion=1,
                                        border=self.DEFAULT_BORDER_SIZE)

        self._horizontal_box_status_list.Add(self._vertical_control_box)

        self._vertical_box.Add(self._horizontal_box_status_list,
                            flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP,
                            border=self.DEFAULT_BORDER_SIZE)

        # Set Sizer
        self._panel.SetSizerAndFit(self._vertical_box)

        #If you want the listctrl and textctrl to have a minimum size
        #open_size = self.GetSize()
        #self.SetMinSize(open_size)

        self.Show()

    def _on_add(self, event):
        pass

    def _on_remove(self, event):
        pass

    def _on_start(self, event):
        pass

class ListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
    def __init__(self, columns, *args, **kwargs):
        super(ListCtrl, self).__init__(*args, **kwargs)
        ListCtrlAutoWidthMixin.__init__(self)

        self.columns = columns
        self._set_columns()

    def _set_columns(self):
        for column_item in sorted(self.columns.values()):
            self.InsertColumn(column_item[0], column_item[1], width=wx.LIST_AUTOSIZE_USEHEADER)

            # If the column width obtained from wxLIST_AUTOSIZE_USEHEADER
            # is smaller than the minimum allowed column width
            # then set the column width to the minumum allowed size
            if self.GetColumnWidth(column_item[0]) < column_item[2]:
                self.SetColumnWidth(column_item[0], column_item[2])

            # Set auto-resize if enabled
            if column_item[3]:
                self.setResizeColumn(column_item[0])
if __name__ == "__main__":

    app = wx.App()
    MainFrame(None)
    app.MainLoop()

打开时:
展开时:
减少: