The wxPython Frame widget is used in almost all wxPython applications. It has the minimize, maximize and close buttons on it as well as the caption along the top that identifies the application. The wx.Frame allows you to modify its styles in such a way that you can remove or disable various buttons and features. In this article, we will look at some of the ways that you can change the behavior of the wx.Frame widget. Specifically, we will cover the following:
It's always a good idea to look at how the default style works and then modify that to see what happens. So let's start with the frame's default style: wx.DEFAULT_FRAME_STYLE. You can create a frame that uses wx.DEFAULT_FRAME_STYLE (or its equivalent) in 3 different ways. The first an easiest is to just do something like this:
import wx ######################################################################## class DefaultFrame(wx.Frame): """ The default frame """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" wx.Frame.__init__(self, None, title="Default Frame") panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = DefaultFrame() app.MainLoop()
This will create a normal frame with all the normal functionality any user would expect. Now let's change it slightly by passing it the wx.DEFAULT_FRAME_STYLE.
import wx ######################################################################## class DefaultFrame(wx.Frame): """ The default frame """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" wx.Frame.__init__(self, None, title="Default Frame", style=wx.DEFAULT_FRAME_STYLE) panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = DefaultFrame() app.MainLoop()
This code does EXACTLY the same thing as the previous code. Now if you do a little research, you'll find out that wx.DEFAULT_FRAME_STYLE is the equivalent of passing the following:
wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN
So let's modify out code one more time to show how that would work.
import wx ######################################################################## class DefaultFrame(wx.Frame): """ The default frame """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" default = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN wx.Frame.__init__(self, None, title="Default Frame", style=default) panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = DefaultFrame() app.MainLoop()
That was easy. Now we're ready to start experimenting!
Let's create a frame that doesn't have a caption. The caption is what holds the buttons along the top of the frame along with the title of the application.
import wx ######################################################################## class NoCaptionFrame(wx.Frame): """""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" no_caption = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CLOSE_BOX | wx.CLIP_CHILDREN wx.Frame.__init__(self, None, title="No Caption", style=no_caption) panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = NoCaptionFrame() app.MainLoop()
When this code is run, the panel is squashed up in the upper left hand corner of the frame. You can resize the frame and the panel will "snap" into place, but it's kind of weird looking. You might also note that you cannot close this application since there is no close button on it. You will need to kill your Python process to close this application.
Some programmers think they need a frame where there's no close button. Well you can't really remove the close button and keep the other buttons at the same time, but you can disable the close button. Here's how:
import wx ######################################################################## class NoCloseFrame(wx.Frame): """ This frame has no close box and the close menu is disabled """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" no_close = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLIP_CHILDREN wx.Frame.__init__(self, None, title="No Close", style=no_close) panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = NoCloseFrame() app.MainLoop()
Of course, you cannot close this application either, so this is a rather annoying piece application. You'll probably want to add a wx.Button that can close it instead.
Sometimes you'll want to create an application that you cannot minimize or maximize. If you're going to go that far, let's make an application that also doesn't show up in the taskbar!
import wx ######################################################################## class NoMaxMinFrame(wx.Frame): """ This frame does not have maximize or minimize buttons """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" no_caption = wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.FRAME_NO_TASKBAR wx.Frame.__init__(self, None, title="No Max/Min", style=no_caption) panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = NoMaxMinFrame() app.MainLoop()
As you can see, we just removed the wx.MINIMIZE_BOX and wx.MAXIMIZE_BOX style flags and added the wx.FRAME_NO_TASKBAR style flag.
Occasionally you'll want to create a frame that cannot be resized. You could use SetSizeHints or you could just set some frame style flags. We'll be doing the latter here:
import wx ######################################################################## class NoResizeFrame(wx.Frame): """ This frame cannot be resized. It can only be minimized, maximized and closed """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" no_resize = wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER | wx.RESIZE_BOX | wx.MAXIMIZE_BOX) wx.Frame.__init__(self, None, title="No Resize", style=no_resize) panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = NoResizeFrame() app.MainLoop()
Note that here we use bitwise operators to remove 3 style flags from the wx.DEFAULT_FRAME_STYLE. As you can see, this gives us a frame that we cannot resize in any way.
This is a rather silly requirement, but I've seen people ask for it. Basically, they want to remove ALL the buttons, but leave the title. Here's how to do that:
import wx ######################################################################## class NoSystemMenuFrame(wx.Frame): """ There is no system menu, which means the title bar is there, but no buttons and no menu when clicking the top left hand corner of the frame """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" no_sys_menu = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.CAPTION | wx.CLIP_CHILDREN | wx.CLOSE_BOX wx.Frame.__init__(self, None, title="No System Menu", style=no_sys_menu) panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = NoSystemMenuFrame() app.MainLoop()
As you can see, there is a title and you can resize the frame, but you cannot maximize, minimize or close the application.
Update: I've had a report that this one doesn't work on Windows XP or Windows 8.1. While I don't particularly care much about that OS at this point, the solution provided was to pass the following style instead of the one above:
no_sys_menu=wx.CAPTION
A lot of programmers ask about this one. They want their application to stay on top of all the others. While there isn't a completely foolproof way to accomplish this, the little recipe below will work most of the time.
import wx ######################################################################## class StayOnTopFrame(wx.Frame): """ A frame that stays on top of all the others """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" on_top = wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP wx.Frame.__init__(self, None, title="Stay on top", style=on_top) panel = wx.Panel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = StayOnTopFrame() app.MainLoop()
Here we just use the default style flag and add on wx.STAY_ON_TOP.
At this point, you should know how to edit almost all the frame's styles. There are a couple of other style flags that are OS dependent (like wx.ICONIZE) or just aren't that useful. If you're interested in those, check out the links below. Otherwise, go forth and use your knowledge wisely.
Note: This code was tested on Windows 7 using Python 2.6.6 with wxPython 2.8.12.1
Copyright © 2024 Mouse Vs Python | Powered by Pythonlibrary