Search code examples
pythonc++wxpythonwxwidgets

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


I am using BoxSizer as a horizontal and vertical layout. However when I use a vertical BoxSizer in a horizontal BoxSizer to contain my buttons so it display vertically beside another element, and when you resize it, it collapse and hide the buttons until you expand it again.

Here is what it looks like by default enter image description here

and here is how it looks like after we resize it to a smaller width enter image description here

As you can see, the buttons is collapsed when resized. How do you stop BoxSizer from being collapsed whenever the window is resized?

Code


Solution

  • Firstly, the semi-rigid rule of posting your code in the question, not on a link, is so that people can see if you have changed it, which you have!

    Your code has now changed, so it becomes difficult to explain changes made to the original code and how they relate to the new code.

    Basically, you have to pay special attention, when using sizers, to the proportion and wx.EXPAND flags. They can cause all sorts of unintended consequences.

    Personally, I would probably have run with a different sizer, perhaps FlexGridSizer for this.

    Here is your original code, with the proportion and expand flags adjusted to perform what I assume you wanted.

    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()
    

    On open:enter image description here
    On expand:enter image description here
    On reduce:enter image description here