Search code examples
pythonresizewxpython

wxpython: Setting minimum frame width / buttons disappearing on resizing


I have a MainWindow frame containing to vertically aligned panels; the top one contains text and buttons (horizontally aligned within the panel), while the bottom one contains content that is easily resizable. I would like to be able to set the minimum width of my frame so that when I resize it down, it does not simply supersede the button and other content in my top panel, which must be visible at all times. After extensive searching, it would seem that there is no built in wx function for this (the closest I found was self.SetMinSize(self.GetSize()), but this also limits the height of the window, which I don't want). I'd also be interesting in knowing if there is a method for doing this with window height as well (though I'm sure it'd be similar to width).

The alternative is finding a way that once the buttons have no more room to move to accommodate resizing, it prevents any further decrease of width of the window (similar to the menubar, where it will stack the drop down menus until there is no more room).

Is there an easy way to do this that I am missing or is this something that would require more extensive hard coding into a custom frame class and used by the MainWindow? Thanks!

Here is the code just in case:

class MainWindow(wx.Frame):
  def __init__(self, parent, title):
    wx.Frame.__init__(self, parent, title=title, size=(850, 800))
    self.exedir = os.getcwd() 
    self.dirname= ''
    #self.SetMinSize(self.GetSize())

    #Set up the initial frames.   
    self.panel1 = wx.Panel(self)  #Create a new panel
    self.panel2 = wx.Panel(self)  #Create a panel for the resulting search
    self.nb = wx.Notebook(self.panel2, size=(wx.EXPAND, 0))

    mainTab = MainTab(self.nb)
    self.nb.AddPage(mainTab, "Main")

    #if page2 is not None:
        #self.nb.AddPage(page2, "Employees")
        #self.nb.Update(self)
    #self.nb.AddPage(page2, "Employees")
    #nb.AddPage(page3, "Tasks")

    self.statusText = wx.StaticText(self.panel1, label="Status: ", size = (50,20))
    self.result = wx.StaticText(self.panel1, label="No Connection", size = (575,20))
    self.result.SetForegroundColour(wx.BLACK) 

    self.buttonConnect = wx.Button(self.panel1, label="Connect")
    self.buttonDisconnect = wx.Button(self.panel1, label="Disconnect")
    self.buttonDisconnect.Disable() #Originally disabled

    self.CreateStatusBar() # A Statusbar in the bottom of the window

    # Setting up the menu.
    configmenu = wx.Menu()
    configmenuConfig = configmenu.Append(wx.ID_PROPERTIES, "&Configuration"," Set up the database configuration")

    taskmenu = wx.Menu()
    taskmenuOpen = taskmenu.Append(wx.ID_OPEN, "&Fill Employee Task database from .csv"," Fill the entire database form a .csv file")
    taskmenuSave = taskmenu.Append(wx.ID_SAVE, "&Save database to .csv"," Backup the database to a crv")
    taskmenuNew = taskmenu.Append(wx.ID_NEW, "&New Project/Program"," Create a new Project/Program")
    taskmenuChange = taskmenu.Append(wx.ID_REVERT, "&Change or delete a Project/Program"," Remove or Modify a Project/Program")
    taskmenuViewTasks =  taskmenu.Append(wx.ID_VIEW_LIST, "&View list of Employee Tasks"," View all the employee's tasks in the database")

    helpmenu = wx.Menu()
    helpmenuHelp = helpmenu.Append(wx.ID_HELP, "&Help"," Instructions on how to use program")
    helpmenuAbout = helpmenu.Append(wx.ID_ABOUT, "&About"," Information about the program")

    exitmenu = wx.Menu()
    exitmenuExit = exitmenu.Append(wx.ID_EXIT, "&Exit"," Quit the program safely")

    employeemenu = wx.Menu()
    employeemenuAddAll = employeemenu.Append(wx.ID_REPLACE_ALL, "&Fill Employee database from .csv"," Fill the entire database form a .csv file")
    employeemenuBackup = employeemenu.Append(wx.ID_DUPLICATE, "&Backup Employee database to .csv"," Backup the database to a .csv file")
    employeemenuViewall = employeemenu.Append(wx.ID_VIEW_LIST, "&View list of Employees"," View all the employees in the database")
    employeemenuAdd = employeemenu.Append(wx.ID_FIND, "&Add Employee"," Add Employee to the database")
    employeemenuModify = employeemenu.Append(wx.ID_REPLACE, "&Modify Employee Fields"," Modify an existing Employee")
    employeemenuDelete = employeemenu.Append(wx.ID_DELETE, "&Delete Employee","Remove and Employee from the database")


    # Creating the menubar.
    self.menuBar = wx.MenuBar()
    self.menuBar.Append(configmenu,"&Config") # Adding the "configmenu" to the MenuBar
    self.menuBar.Append(taskmenu,"&Task") # Adding the "Task" to the MenuBar
    self.menuBar.Append(employeemenu,"&Employees") # Adding the "Employees" to the MenuBar
    self.menuBar.Append(helpmenu,"&Help") # Adding the "Help" to the MenuBar
    self.menuBar.Append(exitmenu,"&Quit") # Adding the "Quit" to the MenuBar

    self.SetMenuBar(self.menuBar)  # Adding the MenuBar to the Frame content.
    self.menuBar.EnableTop(pos=2,enable=False)  #Disable the EMPLOYEE menubar until it is ready
    self.menuBar.EnableTop(pos=1,enable=False)
    # Events for Config
    self.Bind(wx.EVT_MENU, self.OnConfig, configmenuConfig)

    #Set the sizer for the first panel
    panelSizer = wx.BoxSizer(wx.HORIZONTAL)
    panelSizer.Add(self.statusText, proportion=0)
    panelSizer.Add(self.result, proportion=0)
    panelSizer.Add(self.buttonConnect, proportion=0)
    panelSizer.Add(self.buttonDisconnect, proportion=0)

    self.panel1.SetSizer(panelSizer) #Set the panel1 sizer
    self.panel1.Layout()

    #Set the sizer for the second panel
    panel2Sizer = wx.BoxSizer(wx.HORIZONTAL)
    panel2Sizer.Add(self.nb, 0, wx.EXPAND)
    #panel2Sizer.Add(self.grid, 1, wx.EXPAND)
    self.panel2.SetSizerAndFit(panel2Sizer)
    #self.panel2.Layout

    # Set sizer for the  main frame, so we can change frame size to match widgets
    self.windowSizer = wx.BoxSizer(wx.VERTICAL)
    self.windowSizer.Add(self.panel1, proportion=0)  
    self.windowSizer.Add(self.panel2, wx.EXPAND)  

    self.SetSizer(self.windowSizer)
    self.Layout()
    self.Show()

Solution

  • I think one of the easiest ways to prevent the user from making the frame too small is to use its SetSizeHints method. You just pass in your min width/height and your max width/height.

    Here's a simple example:

    self.SetSizeHints(400,400,1200,1200)
    

    You can read more about this method in the documentation. I also found this other question that is similar that has some interesting information: