The WxPython Tutorial



Comments



Description

The wxPython tutorialhttp://www.zetcode.com/wxpython/ Home PyQt4 tutorial The wxPython tutorial Introduction First Steps Menus and Toolbars Layout Management Events Dialogs Widgets Advanced Widgets Drag and Drop in18 Databases Skeletons Custom widgets Using xml resource files GDI Tips and Tricks Gripts The Tetris game wxPython Coding Tools Debugger, Browser, Editor, and more Take a Test Flight Today! www.wingware.com PDF & Image to PDF/A convert, correct, OCR, compress ISO compliant Documents, fast www.detec.com Embedded Java Runtimes Standard & Custom VMs & Profiles OEM Licensing from www.microdoc.com C++ Tutorial 1000's of Great Programmers Bidding Fast & Simple Project Outsourcing. www.GetACoder.com The wxPython tutorial is the largest and most advanced wxPython tutorial available on the Internet. Suitable for beginners and intermediate programmers. ZetCode:: last modified November 25, 2007 (tetris) 2008 Jan Bodnar © 2007 - 1 de 1 27/04/2008 0:58 Introduction to wxPython http://www.zetcode.com/wxpython/introduction/ wxPython IDE Editor,Home Contents and more Free Debugger, Browser, 30-day Trial C++ Tutorial 1000's of Great Programmers Bidding Fast & Simple Project Outsourcing. Introduction to wxPython An Application An application is a computer program that performs a specific task or a group of tasks. Web browser, media player, word processor are examples of typical applications. A term tool or utility is used for a rather small and simple application that performs a single task. A unix cp program is an example of a such a tool. All these together form computer software. Computer software is the broadest term used to describe the operating system, data, computer programs, applications, four different areas. mp3 files or computer games. Applications can be created for Online shopping applications, wikis, weblogs are examples of popular web applications. They are accessed with a web browser. Examples of desktop applications include Maya, specific area. Applications in these area are complex and developed for mobile phones, communicators, pda's and similar. Opera, Open Office or Winamp. Enterprise computing is a large. Applications created for portables include all programs Programming languages There are currently several widely used programming languages. The following list is based on the TIOBE 2007. Programming Community Index. The numbers are from May Position Language Ratings 1 de 9 27/04/2008 0:59 Introduction to wxPython http://www.zetcode.com/wxpython/introduction/ 1 2 3 4 5 6 7 8 9 10 Java C C++ PHP Visual Basic Perl Python C# JavaScript Ruby 19.1% 15.2% 10.1% 8.7% 8.4% 6.2% 3.8% 3.7% 3.1% 2.6% Java is the most widely used programming language. Java various appliances and in creating enterprise applications. excels in creating portable mobile applications, programming Every fourth application is programmed in C/C++. They are applications. C/C++ are the most widely used system standard for creating operating systems and various desktop programming languages. Most famous desktop applications Adobe Photoshop or 3D Max. These two languages also dominate the game programming business. were created in C++. May it be MS Office, Macromedia Flash, PHP dominates over the Web. While Java is used mainly by large organizations, PHP is used by smaller companies and Visual Basic is mainly used in RAD. RAD stands for rapid application development. individuals. PHP is used to create dynamic web applications. Perl, Python and Ruby are the most widely used scripting languages. They share many similarities. They are close competitors. The time of the C# has still not come yet. It was planned to be the next big language. Javascript is a client side programming language, which runs in a browser. It is a de facto standard language and has no competition in it's area. Python Python is a successful scripting language. It was initially developed by Guido van Rossum. It was first 2 de 9 27/04/2008 0:59 Introduction to wxPython http://www.zetcode.com/wxpython/introduction/ released in 1991. Python was inspired by ABC and Haskell programming languages. Python is a high level, general purpose, multiplatform, interpreted language. Some prefer to call it a dynamic language. It is easy to learn. Python is a minimalistic language. One of it's most visible features is that it does not use semicolons nor brackets. Python uses which was released in September 2006. Today, Python is maintained by a large group of volunteers worldwide. intendation instead. The most recent version of python is 2.5, For creating graphical user interfaces, python programmers can choose among three decent options. PyGTK, wxPython and PyQt. The offcial python "toolkit" is TkInter. It is slow, looks terrible on all platforms, it has not been updated for ages. It also depends on Tcl (the tcl language must be included), which is odd. All of the above mentioned toolkits are superior to it. It remains a mystery, why it was not excluded years ago. wxPython wxPython is a cross platform toolkit for creating desktop GUI applications. With wxPython developers can create applications on Windows, Mac and on various Unix systems. wxPython is a wrapper around wxWidgets, which is a mature modules. cross platform C++ library. wxPython consists of the five basic 3 de 9 27/04/2008 0:59 Introduction to wxPython http://www.zetcode.com/wxpython/introduction/ Controls module provides the common widgets found in graphical applications. For example a Button, a Toolbar, or a Notebook. Widgets are called controls under Windows OS. The Core module consists of elementary classes, that are used in the mother of all classes, Sizers, which are used for widget layout, Events, basic geometry classses like Point and Rectangle. The Graphics Device Interface (GDI) is a set of classes used for drawing onto the widgets. This module contains classes for manipulation of Fonts, Colours, Brushes, classes and module functions. These classes are used for Pens or Images. The Misc module contains of various other development. These classes include the Object class, which is logging, application configuration, system settings, working various windows, that form an application. Panel, Dialog, Frame or Scrolled Window. with display or joystick. The Windows module consists of wxPython API wxPython API is a set of functions and widgets. Widgets are widgets are calles controls. We can roughly divide essential building blocks of a GUI application. Under Windows programmers into two groups. They code applications or libraries. In our case, wxPython is a library that is used by application programmers to code applications. Technically, wxPython is a wrapper over a C++ GUI API called wxWidgets. So it is not a native API. e.g. not written directly in Python. know is Java's Swing library. The only native GUI library for an interpreted language that I In wxPython we have lot's of widgets. These can be divided into some logical groups. Base Widgets These widgets provide basic functionality for derived widgets. They are called ancestors. They are usually not used directly. 4 de 9 27/04/2008 0:59 zetcode. Other Widgets These widgets implement statusbar. http://www. They cannot be edited by user. 5 de 9 27/04/2008 0:59 .Introduction to wxPython Top level Widgets These widgets exist independently of each other. Static Widgets These widgets display informatin. Dynamic Widgets These widgets can be edited by users.com/wxpython/introduction/ Containers Containers contain other widgets. toolbar and menubar in an application. Control class. Widgets can inherit functionality from other crucial part of the object oriented programming. The closest class is the wx.zetcode. device context or locale object. All widgets that appear on the screen are windows. There are window. The inheritance is a a hierarchy. For example a color object.Dialog is not a kind of control. The controls are widgets 6 de 9 27/04/2008 0:59 . Not all widgets are controls. Existing classes are called base classes. Examples are sizers. child widgets or descendants. or ancestors.com/wxpython/introduction/ Inheritance There is a specific relation among widgets in wxPython. The button widget inherits from 4 different base classes. There are also classes that are visible but they are not windows. This relation is developed by inheritance. The terminology is borrowed from biology. A button widget is a kind of a small Therefore they inherit from wx. parents. objects that are invisible. For example wx. Widgets form widgets.Introduction to wxPython http://www.Window class. caret object or a cursor object. Inheritance of a button Say we use a button widget in our application. The widgets that inherit we call derived widgets. That's all. The button Each widget that reacts to events must inherit from widget inherits the wx. mother of all objets in wxPython.Object class.com/wxpython/introduction/ that are placed on other widgets called containers. We must choose the right binaries depending on our python version. So does the button widget. is to check that we agree with the licence. This is the Eve.Window class. Finally all objects inherit from wx. The process is very easy provided you have the right OS. Every window can react to events. 7 de 9 27/04/2008 0:59 . There are two basic options. wx.EvtHandler class.Introduction to wxPython http://www.EvtHandler via the wx.EVT_COMMAND_BUTTON_CLICKED event. Unicode version supports other languages than english. By clicking on the button. we launch the wx. Setting up wxPython on Windows XP. That's why we have a separate wx. The only thing we must do. The installer automatically finds the path to the python interpreter. win32-unicode win32-ansi Usually the unicode version is the choice. Setting up wxPython In this section we will show how to set up wxPython library. We can download binaries from the wxPython official web site.Control base class.zetcode. Choose properties. which is located Setting up wxPython on Ubuntu Linux The installation process is even simplier than on Windows XP. This is geared towards developers.exe file. And choose the pythonw. The wxPython library is downloaded and installed on distros might have older packages. We can change Right click on the python icon. We mark the package for installation and click apply. One useful note regarding python interpreter on windows. On my box it is C:\Program Files\Python25\pythonw. cake. The Ubuntu is a great linux distro.x.exe.Introduction to wxPython http://www. Other linux 8 de 9 27/04/2008 0:59 . Change button.com/wxpython/introduction/ Figure: Installing wxPython on Windows XP There is also another separate package. package manager automatically cares about all the necessary dependencies.Administration menu. The installation is done with the Synaptic Package The wxPython package is called python-wxgtkx. Packages on Ubuntu are pretty fresh. It is called win32-docs-demos It contains the famous demo example.zetcode. This is the default behaviour. We can find it under System . Installing wxPython is a piece of Manager. If we click on the python script file a command line window pops up.exe. wxPython is a rapidly our system. in the python install directory. documentation and examples. Press this by associating python programs with the pythonw. Free eval. solid. fun C++ framework for Linux development. we can be forced to install wxPython from sources. To stay up to date. C++ Application Find Vendors of C++ Programming Software in our Business Directory Home ‡ Contents ‡ Top of Page ZetCode last modified June 17.com/wxpython/introduction/ evolving toolkit. 2007 © 2007 Jan Bodnar 9 de 9 27/04/2008 0:59 . Qt: Linux GUI development Mature.Introduction to wxPython http://www.zetcode. py import wx app = wx.Frame(None. Technically wx is a namespace.MainLoop() #!/usr/bin/python # simple.2 First Steps Simple example We start with a very simple example. -1. Here is the code: #!/usr/bin/python # simple. The next line of code 1 de 8 27/04/2008 1:01 . We will analyze the script line by line. import wx This line imports the basic wxPython modules. It provides a name for the script.zetcode. Browser. Our first script will only show a small window. gdi.py The first line is a she-bang followed by the path to a python interpreter. and more Portletsuite WebCMS Over 40 out-of-the-box portlets Direct use in BEA Portal 9.py') frame. prefix.App() frame = wx. The second line is a comment. 'simple. controls.http://www. Debugger.Show() app. It won't do much. modules will start with a wx. Home Contents Easier Python Development Editor.com/wxpython/firststeps/ Python IDE Faster. misc and windows. Namely the core. All functions and objects from the basic will create an application object. The wx. A wx. We will analyze this widget in detail later.http://www.Frame object. The mainloop is an during the life of our application.zetcode. endless cycle. It catches and dispatches all events that exist This was a very simplistic example. It is a top widget in the hierarchy of widgets.py 2 de 8 27/04/2008 1:01 . We can resize the window. -1. we must call the Show() method to actually display it on the screen.Frame widget is a parent widget for a parent parameter we indicate that our widget has no other widgets. Despite this simplicity we can do quite a lot with this window.Frame widget. All this is hidden and provided by default by wheel. the wxPython toolkit. frame = wx.com/wxpython/firststeps/ app = wx. This functionality requires a lot of coding. It has no parent itself. app. 'simple.py') frame. mazimize it.Show() Here we create a wx.App() Each wxPython program must have one application object. There is no reason for reinveinting the Figure: simple.Frame(None.MainLoop() The last line enters the mainloop.Frame widget is an important container widget. If we specify None for parents. minimize it. After we create the wx. default value.DEFAULT_FRAME_STYLE. Those four wx. wx. it has seven parameters. wx.MAXIMIZE_BOX | wx. string title=''.SYSTEM_MENU | wx. A short example follows. As we can see. style = wx.Frame consists of a title bar.RESIZE_BORDER | wx.Frame(wx. The title bar and borders are optional.Frame widget is one of the most important widgets in wxPython.Point pos = wx. The first parameter does not have a parameters are optional. So we did not specify this flag in the style parameter. The other six parameters do have. string name = "f wx.Window parent.Frame wx. 3 de 8 27/04/2008 1:01 .CAPTION | styles we can change the style of the wx. wx.Frame widget.py import wx app = wx.CLOSE_BOX | wx.Defaul wx. By combining various #!/usr/bin/python # nominimizebox.SYSTEM_MENU | wx.App() window = wx.CAPTION | wx. The first three are mandatory.Show(True) app.Size size = wx.RESIZE_BORDER | wx. int id=-1.MAXIMIZE_BOX | wx. style=wx. borders and a central container area.MainLoop() Our intention was to display a window without a mimimize box. It is a container widget.Frame has the following constructor.CLOSE_BOX) window.zetcode.Frame(None.MINIMIZE_BOX | wx. wx.DefaultSize. Actually it can contain any window that is not a frame or dialog.http://www. They can be removed by various flags.com/wxpython/firststeps/ wx. wx.CLIP_CHILDREN.DEFAULT_FRAME_STYLE is a set of default flags. It means that it can contain other widgets. __init__(self.http://www. We 4 de 8 27/04/2008 1:01 . title. parent. 200)) In the constructor we set the width of the wx.App() Size(None.Frame.Frame widget to 250px. id.Frame): def __init__(self.com/wxpython/firststeps/ Figure: A window without a minimize box Size and Position We can specify the size of our application in two ways. A application windows themselves.MainLoop() wx. id.Frame.Show(True) app = wx. But it can differ on various OS platforms or even window managers. parent. Some of them do some programmer can position the window programatically. 200)) self. size=(250. 'Size') app. Or we can call the SetSize() method. We have a size parameter in the constructor of our widget. size=(250.zetcode. title): wx. id. Similarly. we can position our application on the screen. parent. title. The height of the widget to 200px. Some window managers place optimalization. By default the window is placed in the upper left corner of the screen. -1.__init__(self.py import wx class Size(wx. so that windows do not overlap. #!/usr/bin/python # size. Move((800. No need to calculate the width and the height of the screen.MainLoop() There is one particular situation. 250)) self. title): wx. -1.Frame. 0) and takes the whole screen. Simply call the method. int y) SetPosition(wx. title) self. parent.http://www.Frame. We might want to display our window maximized.Point point) SetDimensions(wx. parent. In this case. id.Frame widget.py import wx class Move(wx.Frame): def __init__(self.Show(True) app = wx.Point point) MoveXY(int x.com/wxpython/firststeps/ already saw a pos parameter in the constructor of our wx. id. The Centre() method simply centers the window on the screen. wxPython has a handy method.App() Move(None. we can control the position ourselves. #!/usr/bin/python # move. To maximize our wx. Toss a coin. we call the Maximize() method. If we want to center our application on the screen. wx. the window is positioned at (0.Size size) move a window to the given position move a window to the given position set the position of a window set the position and the size of a window There are several methods to do this. wxPython internally calculates the screen coordinates.Point point. By providing other than the default values.__init__(self. Method Description Move(wx. 'Move') app. 5 de 8 27/04/2008 1:01 .zetcode. Panel): def __init__(self.Centre() self.text.text button1 = wx.GetLabel()) value = value . event): value = int(self. id=button1.__init__(self. id. title): wx.Show(True) app = wx. #!/usr/bin/python # communicate. (10.__init__(self.py import wx class Centre(wx. parent.com/wxpython/firststeps/ #!/usr/bin/python # centre.1 6 de 8 27/04/2008 1:01 . id=button2.Frame.OnPlus.MainLoop() Widgets communicate It is important to know. self.OnMinus.Bind(wx. Follow the next example. '+'.GetLabel()) value = value + 1 self. 10)) button2 = wx.App() Centre(None.SetLabel(str(value)) def OnMinus(self.GetParent().Button(self.http://www.zetcode. event): value = int(self.Panel.GetId()) self.rightPanel. (10.Frame): def __init__(self.text. parent.py import wx class LeftPanel(wx. self. 'Centre') app. -1. id. id): wx. -1. id.EVT_BUTTON. style=wx.BORDER_SUNKEN) self. '-'.Bind(wx.GetId()) def OnPlus(self.Button(self. how widgets can communicate in application. 60)) self.EVT_BUTTON. -1.text = parent. parent.text. parent. title) self. Panel(self. -1.StaticText(self. parent. 1. id): wx.EXPAND | wx.Panel): def __init__(self. it is trivial. -1) leftPanel = LeftPanel(panel. how do we grab the reference to If all the widgets are within one class.Panel. The right panel has one static text. id. -1) self. 200)) panel = wx. '0'. we must get the reference via the hierarchy. 60)) class Communicate(wx. 5) panel.__init__(self. (40.Frame.text. -1. wx. -1) leftPanel = LeftPanel(panel. title): wx. A left and right panel. style=wx.Panel(self.zetcode.BORDER_SUNKEN) self. 'widgets communicate') app.text = wx.http://www. But what if those widgets are created in different classes? In such situations. It is because during the construction of the left panel.rightPanel = RightPanel(panel.ALL.rightPanel = RightPanel(panel.Frame): def __init__(self.__init__(self. panel = wx. size=(280.BoxSizer() hbox. -1) Notice that the right panel must be defined before the left panel. parent.EXPAND | wx. 1.ALL. The left panel has two buttons. -1) hbox = wx.Centre() self. parent. wx. we are looking for the static text widget.rightPanel.Show(True) app = wx. parent.com/wxpython/firststeps/ self.SetSizer(hbox) self. id.App() Communicate(None.Add(leftPanel.SetLabel(str(value)) class RightPanel(wx.Add(self. The question is. -1) self. title. which is defined in 7 de 8 27/04/2008 1:01 . The buttons change the number displayed in the the static text? static text.MainLoop() In our example we have two panels. 5) hbox. id. By calling parent.zetcode. self. relaxed venue.com/wxpython/firststeps/ the right panel.http://www. our example. 3 day courses in the UK or on site. Each widget has a parent argument. 2007 © 2007 Jan Bodnar 8 de 8 27/04/2008 1:01 . The frame widget has reference to the rightPanel. In and right panels. Home ‡ Contents ‡ Top of Page ZetCode last modified June 17. Learn at a friendly. Finally.GetParent() we get reference to the frame widget.text The answer is here.GetParent().text = parent.rightPanel. we cannot get reference to non existing widget. right panel has reference to the static text widget. Logically. parent is a panel on which we display both left Figure: how widgets communicate Python Database Interface Python Training Courses Easily connect Python to all your databases. A wx.MenuBar() file = wx. It is a group of commands located in various menus. id.Menus and Toolbars in wxPython http://www.MenuItem. 150)) menubar = wx. Editor. parent.zetcode.Frame): def __init__(self. Just a few lines of code. #!/usr/bin/python # simplemenu. 'Quit application') menubar.Menu() file. learn a new application. parent.MenuBar. id.Frame.SetMenuBar(menubar) self.__init__(self. size=(250. title.Menu and a wx.Append(-1. While in console applications you had to remember all those arcane commands. a wx. title): wx. 'Quit'. '&File') self.py import wx class SimpleMenu(wx. here we have most of the commands grouped into logical parts. Browser. To implement a menubar in wxPython we need Figure: A MenuBar architecture A Simple menu example Creating a menubar in wxPython is very simple.Centre() 1 de 15 27/04/2008 1:02 .Append(file. There are accepted standards that further reduce the amount of time spending to to have three things.com/wxpython/menustoolbars/ HomeDebugger. and more Take a Contents Test Flight Today! wxPython Coding Tools Get a WebSearch toolbar Try these Websearch toolbars built with Dynamic Toolbar Menus and Toolbars in wxPython Creating a MenuBar A menubar is one of the most visible parts of the GUI application. 'Quit'. -1.Frame widget.Append(-1. 'simple menu example') app. The & character creates an accelerator key. we will create a wx. It was created by the Append() method behind menubar.Menus and Toolbars in wxPython self.MenuItem manually. This feature is not commoly seen in applications. wx. we call It sets up the menubar. The menubar is implemented outside the main window. In the end. This method belongs to the wx.MenuItem explicitely. file.MainLoop() http://www.zetcode. But similar thing can be seen on Mac OS. '&File') self. Figure: A simple menu example A dockable menubar Under Linux. file = wx.SetMenuBar(menubar) After that. 'Quit application') We append a menu item into the menu object. the SetMenuBar() method. The last parameter defines the short helpstring that is displayed on the statusbar. we can create a dockable menubar.com/wxpython/menustoolbars/ menubar = wx. 2 de 15 27/04/2008 1:02 . This way the menu is accessible via the alt + F shortcut. The first parameter is the id of the menu item. we append a menu into the menubar. The second parameter is the name of the menu item. when the menu item is selected.Append(file.MenuBar() First we create a menubar object.Menu() Next we create a menu object. Mac users do not have a menubar in the toplevet application window.Show(True) app = wx. Later on.App() SimpleMenu(None. The character that follows the & is underlined. Here we did not create a the scenes. id.MB_DOCKABLE) We create a dockable menubar by providing a wx. '&Help') self. -1. '&Edit') menubar.Frame): def __init__(self. '&View') menubar.Centre() self.Frame.Show(True) app = wx. '&Insert') menubar. '&File') menubar.MB_DOCKABLE) file = wx. '&Tools') menubar. 'Dockable menubar') app. parent.Append(edit.Append(help.Menu() help = wx. Figure: A dockable menubar 3 de 15 27/04/2008 1:02 .Append(tool.Menu() insr = wx.Append(insr.MB_DOCKABLE flag to the constructor.Menus and Toolbars in wxPython http://www.Menu() menubar. title): wx. title) menubar = wx.Append(form.py import wx class Dockable(wx.Menu() view = wx.Menu() form = wx.MenuBar(wx.Append(view. '&Format') menubar.zetcode.App() Dockable(None.Menu() tool = wx. id.com/wxpython/menustoolbars/ #!/usr/bin/python # dockable.__init__(self. parent.MenuBar(wx.MainLoop() menubar = wx.Append(file.SetMenuBar(menubar) self.Menu() edit = wx. SetBitmap(wx. than to move a mouse pointer to the menubar. id. So if we press Ctrl + Q.Show(True) def OnQuit(self. event): self. The & character specifies an accelerator key. events In the next section we will further enhance our menu example.com/wxpython/menustoolbars/ Icons. We will see.App() MenuExample(None.zetcode. id. that would not know the quickly with our applications. So far we have created menuitems indirectly. We have specified Ctrl + Q characters.Frame. Icons make our applications more visually attractive. click a File menu and select the Save commnand.MenuItem.png')) file.Bitmap('icons/exit. title): wx. '&Quit\tCtrl+Q') quit. 1.Menus and Toolbars in wxPython http://www. 1.Frame): def __init__(self. title. -1.Centre() self. 150)) menubar = wx. We will see. It is more handy to press this shortcut. Further. There are not many people. They enable us to work more Ctrl + S one. '') app. id=1) menubar.py import wx class MenuExample(wx.MainLoop() quit = wx.png')) file.Close() app = wx.MenuItem(file.MenuBar() file = wx.Menu() quit = wx. The following character is underlined. Shortcuts are a productivity boost to most users.SetBitmap(wx.MenuItem(file. size=(250.OnQuit. shortcuts.Append(file. We put a tab character between the & 4 de 15 27/04/2008 1:02 . they help us understand the menu commands. parent. #!/usr/bin/python # menuexample.__init__(self. One of the most widely used shortcut is the meaning of this shortcut. how we can add icons to our menus.EVT_MENU. parent. we have to manually create a wx.Bind(wx. We will also briely touch events. The actual shortcut is defined by the combination of characters. '&File') self. '&Quit\tCtrl+Q') quit. Shortcuts are not a relict from the past. we close the application.AppendItem(quit) If we want to add shortcuts and icons to our menus.AppendItem(quit) self.SetMenuBar(menubar) self. how we can add shortcuts to our menus.Bitmap('icons/exit. self. To provide an icon for a menuitem.OnQuit. id=1) If we select a quit menu item or press a keyboard shortcut. size=(350. the OnQuit() method closes the application. 250)) menubar = wx. between them. title. title): wx. Working with events is very easy and straightforward in wxPython. parent. we manage to put some space method. We Figure: A menu example Submenus Each menu can also have a submenu.EVT_MENU event is generated.zetcode.__init__(self.Frame): def __init__(self. open. print preview with a single separator. we call a SetBitmap() self. self. status bar or navigation bar into a submenu called toolbars. We bind an event handler to the event. The event handler is a method. id. how we can create submenus and menu separators.EVT_MENU. In our example. parent. that is being called. a wx. so we have to give a unique id to each of them. This way. It is a simple line.Menu() 5 de 15 27/04/2008 1:02 . There can be several menuitems. #!/usr/bin/python # submenu. For example we can place commands that hide/show various toolbars like personal bar.Bind(wx. save from commands like print.com/wxpython/menustoolbars/ character and the shortcut. Within a menu. we can seperate commands with a separator.MenuBar() file = wx. address bar. A manually created menuitem is appended to the menu by calling the AppendItem() method.py import wx ID_QUIT = 1 class SubmenuExample(wx.Menus and Toolbars in wxPython http://www. will talk about events in a separate chapter. This way we can group similar commnads into groups.Frame. In our example we will see. It is common practice to separate commands like new. id. 6 de 15 27/04/2008 1:02 .EVT_MENU..Append(file.') imp. Then we append menu items. event): self.Append(-1. imp = wx. '&Open') file.AppendMenu(-1. id=ID_QUIT) menubar.App() SubmenuExample(None..OnQuit.Close() app = wx. 'Import bookmarks.Append(-1.') imp. 'Submenu') app. 'I&mport'.zetcode.Append(-1.Centre() self. 'Import newsfeed list. 'Import newsfeed list. '&File') self. 'I&mport'.AppendItem(quit) self. -1.SetMenuBar(menubar) self. '&Quit\tCtrl+W') quit.Append(-1...') file..AppendSeparator() A menu separator is appended with the AppendSeparator() method. imp) Creating a submenu is trivial...Append(-1.') file.Append(-1.Append(-1.Menus and Toolbars in wxPython file. '&Save') file. imp) quit = wx.MainLoop() file.MenuItem(file.. 'Import bookmarks. ID_QUIT. First..Menu() imp. 'Import mail. A submenu is created by calling the AppenMenu() on the menu object..Show(True) def OnQuit(self.Bitmap('icons/exit.Menu() imp.Bind(wx.Append(-1. '&New') file.AppendSeparator() http://www. we create a menu..') imp.SetBitmap(wx..png')) file.') imp. 'Import mail.Append(-1. self.com/wxpython/menustoolbars/ imp = wx.AppendMenu(-1. size=(350.CreateToolBar() self.Bind(wx. ''. parent. title.png')) self.Bind(wx.statusbar = self.Append(view. parent. '&File') menubar.EVT_MENU. 'Show toolbar'.Append(ID_TOOL.ITEM_CHECK view.SetMenuBar(menubar) self. 'Show Toolbar'.toolbar. normal item check item radio item #!/usr/bin/python # checkmenuitem.ITEM_CH self.CreateStatusBar() self. '&View') self.EVT_MENU.AddLabelTool(3.Menus and Toolbars in wxPython http://www. wx. 'Show Statusbar'. self.zetcode.shtl = view.Menu() self. id. True) view.Bitmap('icons/quit.Append(ID_STAT. id=ID_TOOL) menubar.Check(ID_TOOL.MenuBar() file = wx.ToggleToolBar.ToggleStatusBar.Centre() self.shst = view. 250)) menubar = wx. id.Append(file. kind=wx.Frame. True) self.Show(True) 7 de 15 27/04/2008 1:02 . 'Show statubar'.Menu() view = wx.py import wx ID_STAT = 1 ID_TOOL = 2 class CheckMenuItem(wx. id=ID_STAT) self. kind=wx.__init__(self.com/wxpython/menustoolbars/ Figure: A submenu example Various menu items There are tree kinds of menu items.toolbar = self.Check(ID_STAT.Frame): def __init__(self. title): wx. self. we set a kind parameter to wx.shst. 'check menu item') app.ITEM_NORMAL.Check(ID_STAT.IsChecked(): self. def ToggleStatusBar(self.Hide() We show or hide the statusbar according to the state of the check menu method. We find out the state of the check menu item with the IsChecked() 8 de 15 27/04/2008 1:02 . -1.statusbar. 'Show toolbar'.Check(ID_TOOL. item.com/wxpython/menustoolbars/ self.ITEM_CHECK) If we want to append a check menu item.zetcode.Show() else: self. view. kind=wx. Same with toolbar.Hide() def ToggleToolBar(self.statusbar.ITEM_CHECK.Append(ID_TOOL. 'Show statubar'.Menus and Toolbars in wxPython def ToggleStatusBar(self.toolbar.ITEM_CHECK) self.Show() else: self.shst. So we check both menu items with the Check() method. 'Show Toolbar'. 'Show Statusbar'.IsChecked(): self. The Append() method returns a wx. event): if self. both statusbar and toolbar are visible.IsChecked(): self.shst = view. True) view. kind=wx.Append(ID_STAT.shtl = view.statusbar. True) When the application starts.Hide() app = wx. The default parameter is wx. event): if self.MainLoop() http://www.toolbar.Show() else: self.statusbar.shtl.MenuItem.App() CheckMenuItem(None. event): if self. zetcode. self. 'Minimize') self. id. we get a context menu.GetId()) close = wx. go back or view page source.EVT_MENU.AppendItem(close) self.MenuItem(self.OnRightDown) self.Menu): def __init__(self. If we right click on a toolbar. id=minimize. 'Close') self. -1. self.parent = parent minimize = wx.GetPosition()) app = wx. parent.py import wx class MyPopupMenu(wx. in a Firefox web browser.Frame.__init__(self.MainLoop() class MyPopupMenu(wx. wx. id=close.Bind(wx.Menu): def __init__(self. when we right click on a web page.parent. 150)) self.NewId().Bind(wx.AppendItem(minimize) self. parent.EVT_MENU. we get another context menu for managing #!/usr/bin/python # contextmenu. size=(250.Menus and Toolbars in wxPython http://www. For example. wx. Context menus are sometimes called popup menus.OnClose.Iconize() def OnClose(self. toolbars. Here we can reload a page.Bind(wx. event): self.Show() def OnRightDown(self. id. event): self.parent.EVT_RIGHT_DOWN.Frame): def __init__(self.App() frame = ContextMenu(None. 'context menu') app. event. parent): wx.com/wxpython/menustoolbars/ Figure: check menu item Context menu It is a list of commands that appears under some context. self.Close() class ContextMenu(wx. title): wx.__init__(self) self.NewId(). event): self.OnMinimize.GetId()) def OnMinimize(self.PopupMenu(MyPopupMenu(self).MenuItem(self. parent): 9 de 15 27/04/2008 1:02 .Menu. title.Center() self. Menus and Toolbars in wxPython http://www.AddLabelTool(wx. wx. id.ID_EXIT. #!/usr/bin/python # simpletoolbar. self. we call the GetPosition() menthod.EVT_TOOL. self. event./icons/exit.py import wx class SimpleToolbar(wx. we call the PopupMenu() method. id=wx.Show(True) def OnExit(self. int winid=-1.Bind(wx. title.Menu. The first parameter is the menu to be shown. String name=ToolBarNameStr) To create a toolbar. Here we define two commands.ID_EXIT) self.__init__(self) We create a separate wx.__init__(self. self.Centre() self.GetPosition()) In the OnRightDown() method. title): wx.Bitmap('. appears.Bind(wx.Realize() self. size=(300.Frame): def __init__(self. event): self. parent. we call the CreateToolBar() method of the frame widget. id. Close and minimize window. The context menus appear at the point of the mouse cursor.App() SimpleToolbar(None. -1.zetcode. Toolbars provide a quick access to the most frequently used commands. def OnRightDown(self. where the context menu get the actual mouse position.Close() app = wx. The second parameter is the position.png')) toolbar.Menu class. parent.EVT_RIGHT_DOWN.. 'simple toolbar') 10 de 15 27/04/2008 1:02 .com/wxpython/menustoolbars/ wx.Frame. ''.PopupMenu(MyPopupMenu(self). we call the OnRightDown() method.OnExit. CreateToolBar(long style=-1.CreateToolBar() toolbar. 200)) toolbar = self. For this. event): self. To Toolbars Menus group all commands that we can use in an application.OnRightDown) If we right click on the frame. we use the wx.EVT_RIGHT_DOWN event binder. This method shows the context menu. MainLoop() http://www.zetcode.Bitmap('.AddLabelTool(wx. Figure: simple toolbar If we want to create more than one toolbars. wx. ''.Bitmap('. 200)) vbox = wx. ''..AddLabelTool(wx. title): wx. toolbar. On windows it is. ''.png')) toolbar1.ToolBar(self. -1) toolbar2. title. wx. parent. #!/usr/bin/python # toolbars./icons/exit. Calling this method is not obligatory on Linux.png')) toolbar2. id..__init__(self. wx.OnExit..Realize() 11 de 15 27/04/2008 1:02 . we use the wx.ID_EXIT.VERTICAL) toolbar1 = wx.ID_ANY.AddLabelTool(wx..Menus and Toolbars in wxPython app.ID_ANY. ''. we call the Realize() method. wx.Bitmap('.ID_EXIT) To handle toolbar events. parent.ToolBar(self. size=(300. ''. -1) toolbar1.AddLabelTool(wx.EVT_TOOL event binder.png')) To create a toolbar button.com/wxpython/menustoolbars/ toolbar./icons/open.Realize() After we have put our items to the toolbar./icons/new.Realize() toolbar2 = wx. wx. id./icons/save.png')) toolbar1./icons/exit.png')) toolbar1.ID_ANY..ID_EXIT.Bitmap('. we must do it differently.AddLabelTool(wx.BoxSizer(wx.Frame): def __init__(self. self. self. id=wx. we call the AddLabelTool() method.EVT_TOOL.py import wx class Toolbars(wx.Frame.Bind(wx.Bitmap('. __init__(self. ''.zetcode. ''.SetSizer(vbox) self.Add(toolbar1. parent./icons/select.Add(toolbar2. 0. 'toolbars') app.Bitmap('. id.com/wxpython/menustoolbars/ self..ID_ANY. parent. -1.gif')) toolbar.gif')) 12 de 15 27/04/2008 1:02 ..CreateToolBar(wx. 300)) toolbar = self.ID_EXIT) self.gif')) toolbar. size=(240.ID_ANY.Menus and Toolbars in wxPython vbox.Show(True) def OnExit(self.gif')) toolbar...OnExit.. Figure: toolbars Sometimes we need to create a vertical toolbar. -1) . wx. ''. self.EXPAND) http://www.ToolBar(self.AddLabelTool(wx.App() Toolbars(None.Close() app = wx. 0.AddLabelTool(wx./icons/shapeed..Frame. Vertical toolbars are often seen in graphics applications like Inkscape or Xara Xtreme. id. ''. id=wx.Bitmap('./icons/freehand.TB_VERTICAL) toolbar.AddLabelTool(wx. And put them into a vertical box.ToolBar(self.Bitmap('.Frame): def __init__(self.ID_ANY. wx. wx. title): wx. #!/usr/bin/python # verticaltoolbar.Bind(wx.Bitmap('./icons/pen.py import wx class VerticalToolbar(wx. event): self.EVT_TOOL. title.EXPAND) vbox.Centre() self. wx. wx.MainLoop() toolbar1 = wx. wx.AddLabelTool(wx. toolbar2 = wx.ID_ANY. -1) We create two toolbar objects. .ID_ANY.Bitmap('. we will show./icons/text.AddLabelTool(wx.ID_ANY. ''... event): self. toolbar.com/wxpython/menustoolbars/ wx. toolbar..ID_ANY./icons/rectangle.ID_ANY. toolbar. 'vertical toolbar') app.AddLabelTool(wx.App() VerticalToolbar(None.Realize() ''.gif')) wx./icons/qs. ''. how we can enable and disable toolbar buttons.zetcode.CreateToolBar(wx.Bitmap('.ID_ANY. We will also see a separator line.Bitmap('. ''.TB_VERTICAL) Here we create a vertical toolbar. http://www.Bitmap('.AddLabelTool(wx..MainLoop() toolbar = self.Close() app = wx.gif')) . Figure: vertical toolbar In the following example.AddLabelTool(wx. -1..Bitmap('./icons/ellipse.Show(True) def OnExit(self. toolbar./icons/select. toolbar. #!/usr/bin/python 13 de 15 27/04/2008 1:02 .ID_ANY.Bitmap('. I have borrowed icons from the Xara Xtreme graphics application. ''.. wx.AddLabelTool(wx.AddLabelTool(wx..gif')) self.gif')) wx.Menus and Toolbars in wxPython toolbar.gif')) wx. wx./icons/freehand.Centre() self.gif')) toolbar. ''. count <= 5: self.toolbar.AddLabelTool(wx. wx.ID_REDO.toolbar.EnableTool(wx. True) def OnRedo(self. We do it by calling the 14 de 15 27/04/2008 1:02 ./icons/undo..toolbar. The undo and redo butons are self./icons/exit.Bitmap('.EVT_TOOL.Frame): def __init__(self.EVT_TOOL.count == 4: self.toolbar = self.__init__(self.ID_REDO.count > 1 and self. we have three toolbar buttons.py import wx http://www.count = 5 self. event): if self. size=(250. id=wx. One button is for exiting the application. parent. ''. False) self.count = self.1 if self.EnableTool(wx.ID_REDO.Close() app = wx.png')) self. event): if self. id.Menus and Toolbars in wxPython # enabledisable.toolbar.count == 1: self.count < 5 and self.toolbar. id=wx. 'enable disable') app.. ''.zetcode.toolbar.toolbar.ID_UNDO) self.count >= 1: self. False) self.AddLabelTool(wx. self.ID_EXIT) self.ID_UNDO.MainLoop() In our example.EnableTool(wx. False) if self.ID_UNDO. -1.toolbar. title): wx. 150)) self.ID_UNDO.Frame.ID_REDO) self.png')) self.App() EnableDisable(None.com/wxpython/menustoolbars/ class EnableDisable(wx.EnableTool(wx.ID_REDO.count + 1 if self.EnableTool(wx.EVT_TOOL.OnExit. They simulate undo/redo functionality in an application. disabled accordingly. event): self.count . id=wx.OnUndo. self.toolbar. the redo button is disabled.Realize() self.OnRedo. parent. id./icons/redo.Centre() self.AddSeparator() self.toolbar.AddLabelTool(wx. False) if self.Bind(wx. wx. wx.Show(True) def OnUndo(self.ID_REDO. see tips and tricks) We have 4 changes.Bind(wx.ID_EXIT.EnableTool(wx. The other two buttons are undo and redo buttons.toolbar. self.toolbar.AddSeparator() In the beginning.Bitmap('.count == 2: self.Bitmap('.Bind(wx.count == 5: self.count = self. (for a real example. ''.png')) self. title..CreateToolBar() self. True) def OnExit(self. change. True) We simulate undo and redo functionality.count . After undoing the first method.com for All Your Needs On the Costa del Sol food at your fingertips www. we call the AddSeparator() method. toolbar.com Home ‡ Contents ‡ Top of Page ZetCode last modified June 19.ID_REDO.EnableTool(wx.yourmenupages. the undo button is disabled.count == 4: self. If there is nothing left to undo. We can create some logical groups within a line.count <= 5: self.com/wxpython/menustoolbars/ EnableTool() method.toolbar. False) if self. We can separate various groups of buttons by a small vertical def OnUndo(self.toolbar.Menus and Toolbars in wxPython http://www. we enable the redo button.EnableTool(wx. We have 4 changes. event): if self.zetcode. 2007 © 2007 Jan Bodnar 15 de 15 27/04/2008 1:02 .ID_UNDO.count = self.1 if self.count > 1 and self. Use Business. Same logic applies for the OnRedo() Figure: enable disable buttons Menu Online menu directory Find Printers of Customized Menus.count == 1: self. To do this. Figure: before resizement Figure: after resizement 1 de 17 27/04/2008 1:03 . A programmer must manage the layout of the application. you must completely redo your layout. Size Clips. Manufacturer with worldwide sales. in real world programs. For example. so I often use absolute positioning to explain a topic. There might be situations.zetcode. the size and the position of a widget do not change. If we resize the window. In wxPython we have two options.com/wxpython/layout/ Home Contents Python IDE Faster.TextCtrl does not change as we would expect. programmers use sizers. But mostly. Sizers. I do not want to make the examples too difficult. In our example we have a simple skeleton of a text editor. This is Absolute Positioning The programmer specifies the position and the size of each widget in pixels.Layout management in wxPython http://www. Debugger. Browser. my tutorials. the size of out wx. Easier Python Development Editor. Those widgets are placed inside not an easy task. and more Garment Size Markers Mini Markers. Layout management in wxPython A typical application consists of various widgets. where we can possibly use absolute positioning. you have to understand several things. if you resize a window applications look different (crappy) on various platforms changing fonts in your application might spoil the layout which is tedious and time consuming if you decide to change your layout. absolute positioning sizers container widgets. When you use absolute positioning. zetcode.Centre() self.BoxSizer wx. '&File') menubar.com/wxpython/layout/ #!/usr/bin/python # absolute.Menu() edit = wx. id. '&Help') self.Append(edit.TextCtrl(panel. -1. size=(250. -1.__init__(self.StaticBoxSizer wx. size=(250. we mentioned by absolute positioning.Show(True) app = wx.Frame. -1). we provide the default position for the widget. In our case.MainLoop() wx. 150)) self.py import wx class Absolute(wx.GridSizer wx. title): wx. wx.Menu() menubar.TextCtrl(panel. -1). '') app. 180)) panel = wx. pos=(-1.Append(help.Frame): def __init__(self. size=(250. We can choose among these sizers.MenuBar() file = wx. id.App(0) Absolute(None. parent.Layout management in wxPython http://www. pos=(-1.TextCtrl. -1) menubar = wx.SetMenuBar(menubar) wx. Using sizers Sizers do address all those issues. title. The width is 250px and the height 150px. -1.GridBagSizer 2 de 17 27/04/2008 1:03 .Append(file.Panel(self. parent. 150)) We do the absolute positioning in the constructor of the wx.Menu() help = wx. '&Edit') menubar.FlexGridSizer wx. Frame. Actually.__init__(self. -1.Append(edit. which is not given to the borders.zetcode. We can put only one widget inside the wx. wx. 180)) menubar = wx.Menu() edit = wx.Frame widget. integer flag = 0. we need to look The proportion parameter defines the ratio of how will the widgets change in the defined orientation.MenuBar() file = wx. size=(250. box = wx.Show(True) app = wx. parent.Append(file. we placed the wx.Window window.HORIZONTAL.App(0) Sizer(None. We can put another sizer into an existing sizer.Append(help.com/wxpython/layout/ Figure: before resizement Figure: after resizement #!/usr/bin/python # sizer.TextCtrl(self.MainLoop() Ok. '&Edit') menubar. The child widget occupies all the space.Layout management in wxPython http://www. id.TextCtrl inside the wx. integer border = 0) The orientation can be wx.SetMenuBar(menubar) wx.Add(wx.Frame widget has a special built-in sizer. menu.Centre() self.BoxSizer is done via the Add() method.BoxSizer This sizer enables us to put several widgets into a row or a column.BoxSizer(integer orient) box. 1. integer proportion=0.Menu() menubar. In order to understand it. title): wx. This way we can create very complex layouts.Frame container.py import wx class Sizer(wx. Adding widgets into the at its parameters. wx. title. The wx. the code example was a bit tricky. parent. '&File') menubar. -1) self.Frame): def __init__(self. so you are saying that you don't see any sizers in the example? Well. and 3 de 17 27/04/2008 1:03 .Menu() help = wx.VERTICAL or wx. toolbar and the statusbar. id. Let's assume we have tree buttons with the proportions 0. '') app. '&Help') self. We can choose between these flags: wx.Add(midPan.BOTTOM Figure: border around a panel #!/usr/bin/python # border. we can also define the alignment of our widgets. wx.SetBackgroundColour('#ededed') vbox.Centre() self. We do it with the following 4 de 17 27/04/2008 1:03 . They are added into a horizontal wx. 20) panel.ALL.Panel(panel. our widget will use all the space that has been allotted to flags : it. In order to apply border we need to define sides. We add some space between widgets in pixels. wx.com/wxpython/layout/ 2.BoxSizer(wx. '') app.__init__(self.LEFT | wx.ALL wx.Frame): def __init__(self. parent. e. If we use wx.EXPAND | wx. -1. size=(250. 20) In border.SetBackgroundColour('#4f5049') vbox = wx. wx.BoxSizer.Panel(self. We can combine them with the | operator. -1) panel. Lastly.Layout management in wxPython http://www.py we have placed a 20 px border around a midPan panel. 200)) panel = wx. Button with proportion 0 will not change at all. We can control the border between the widgets.ALL.EXPAND flag. -1) midPan.BOTTOM. 1.LEFT wx.BoxSizer.EXPAND | wx.g wx. where the border will be used.py import wx class Border(wx. Button with proportion 2 will change twice more than the one with proportion 1 in the horizontal dimension.RIGHT wx. title.zetcode.ALL applies the border size to all four sides.Frame. id. With the flag parameter you can further configure the behaviour of the widgets within a wx. 1.SetSizer(vbox) self.App() Border(None.MainLoop() vbox.TOP wx. title): wx.Show(True) app = wx. parent.Add(midPan. id.VERTICAL) midPan = wx. 350)) panel = wx.TOP. 1) vbox.SetFont(font) hbox2. 10)) hbox2 = wx.py import wx class GoToClass(wx.TextCtrl(panel. 10) vbox.ALIGN_RIGHT wx.SystemSettings_GetFont(wx. Figure: A go to class window #!/usr/bin/python # gotoclass.StaticText(panel. -1) font = wx.LEFT | wx.RIGHT | wx.BoxSizer(wx.Layout management in wxPython http://www. 0. 10) vbox.EXPAND | wx.ALIGN_CENTER_VERTICAL wx.Frame): def __init__(self. id. wx.BoxSizer(wx. 0. 10)) 5 de 17 27/04/2008 1:03 .SYS_SYSTEM_FONT) font. wx.Add(st1. size=(390. -1.Panel(self.VERTICAL) hbox1 = wx.Add(hbox2.StaticText(panel. 0) vbox. parent.SetFont(font) hbox1.Add(tc.TOP. 'Class Name') st1.Add(hbox1.Add((-1.LEFT | wx. id.RIGHT.Add((-1. -1.__init__(self. 'Matching Classes') st2.zetcode.ALIGN_CENTER Go To Class wx.ALIGN_LEFT wx. wx.SetPointSize(9) vbox = wx.ALIGN_BOTTOM wx. 0.com/wxpython/layout/ wx.Frame.ALIGN_TOP wx. -1) hbox1.HORIZONTAL) st1 = wx.HORIZONTAL) st2 = wx. title): wx.Add(st2. parent. 8) tc = wx. title.BoxSizer(wx.ALIGN_CENTER_HORIZONTAL In the following example we introduce several important ideas. Add(hbox4.SetFont(font) hbox4.LEFT.EXPAND flag. wx.Button(panel. wx. But there is one real constraint.SetFont(font) hbox4.Add(cb3. We put then five horizontal sizers into it.Add((-1.BOTTOM. In our example.SetFont(font) hbox4. 25)) We already know that we can control the distance among widgets by combining the flag parameter with the border parameter. wx.CheckBox(panel.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT) font. wx.ALIGN_RIGHT | wx. If we omit wx.HORIZONTAL) btn1 = wx.MainLoop() The layout is straitforward. size=(70. The proportion. 25)) hbox5 = wx. The buttons 6 de 17 27/04/2008 1:03 . size=(70. 'Non-Project classes') cb3.zetcode.ALIGN_RIGHT | wx. wx.BOTTOM .EXPAND. We create one vertical sizer.LEFT. -1. With the Add() method. 'Go To Class') app.Add(btn1. The buttons should not change their size. 0.TE_MULTILINE) hbox3.CheckBox(panel. 0.Layout management in wxPython http://www. The proportion must be zero. On my platform.EXPAND. wx. What we can do is to give 10px to the bottom. 10) vbox.HORIZONTAL) tc2 = wx. -1.BoxSizer(wx. wx. 30)) hbox5. 5) vbox. 'Ok'. we can vbox. 10) vbox. we can add some extra space. 10) vbox. need different values.EXPAND flag.Add(hbox3.SetSizer(vbox) self. So I set the font size to 9px.TextCtrl(panel. In the Add() method we can specify only one border for all given sides. 0. 10) cb3 = wx.Add(hbox5. 'Close'.LEFT | wx.Add((-1.LEFT | wx.Button(panel. How do we do it? Three things are important to achieve this.Add((-1. 0) btn2 = wx.SetPointSize(9) The default system font was 10px.RIGHT | wx. -1. 10) panel.Add(hbox5. 1.Add(cb1) cb2 = wx.Add(hbox3.Add(tc2. wx.RIGHT. 0. 1. vbox. or 0px. 'Case Sensitive') cb1. -1.com/wxpython/layout/ hbox3 = wx.RIGHT | wx.BoxSizer(wx. We must not specify wx.HORIZONTAL) cb1 = wx. But we cannot give 25 px to the bottom.Add(cb2. -1. it was too big for this kind of window.EXPAND) vbox. 25)) hbox4 = wx. -1. -1. we give 10px to the right and to the left. 1.Show(True) app = wx. style=wx. font = wx. the align flag and the wx. 0.CheckBox(panel.BoxSizer(wx. 0.Centre() self.App() GoToClass(None. when we resize our window. 10) We place the two buttons on the right side of the window. 'Nested Classes') cb2. 30)) hbox5.Add(btn2.LEFT. 10) vbox. wx. So if we insert widgets and space as well.RIGHT.LEFT | wx. orient=wx. 2) grid1.ALIGN_RIGHT flag.RadioButton(panel2. We will create a find/replace dialog. -1.zetcode. -1) vbox = wx. we must specify the wx. -1.VERTICAL) panel = wx. 'Replace with: '. Exactly.VERTICAL) # panel1 panel1 = wx.HORIZONTAL) sizer21 = wx. -1))) panel1. So if we specify wx.Add(wx.__init__(self.StaticBoxSizer(wx.Add(wx. -1) grid1 = wx.Add(wx.com/wxpython/layout/ occopy only the area that has been alotted to it. the buttons are placed to the Figure: A complex example using wx.VERTICAL) sizer21. 5)). -1) hbox2 = wx. 0. Find/Replace Dialog A complex example follows.TOP. 365)) vbox_top = wx.BoxSizer(wx.Dialog. -1.ALIGN_CENTER_VERTICAL) grid1. parent. The horizontal sizer spreads from the left side of the window right side.Layout management in wxPython http://www. -1. (5. 9) # panel2 panel2 = wx. wx.RadioButton(panel2.ComboBox(panel1.BoxSizer(wx. 'Find: '. (5.StaticText(panel1. title.Add(wx. style=wx. -1.BoxSizer #!/usr/bin/python # Find/Replace Dialog import wx class FindReplace(wx. title): wx. -1))) grid1. size=(255. to the right side. 'Backward')) 7 de 17 27/04/2008 1:03 . 0. size=(120.Panel(panel.BOTTOM | wx.Panel(self. id.ALIGN_RIGHT flag.SetSizer(grid1) vbox. wx.Add(panel1. This kind of dialog can be found in the Eclipse IDE.StaticBox(panel2.StaticText(panel1. wx. 0.RB_GROUP)) sizer21. id.Panel(panel. 'Forward'.BoxSizer(wx. 'Direction'). -1. as we wanted. And finally.Add(wx.Dialog): def __init__(self.ALIGN_CENTER_VERTICAL) grid1. -1.Add(wx.ComboBox(panel1.GridSizer(2. parent. size=(120. 5)). SetSizer(sizer4) vbox. 'Find'. -1) sizer3 = wx.GridSizer(2. wx. 2. So the parent panel will have a vertical 8 de 17 27/04/2008 1:03 .com/wxpython/layout/ sizer22 = wx. 2. -1) sizer5 = wx.Panel(panel.BOTTOM.CheckBox(panel3. style=wx. -1))) panel5.EXPAND | wx. 'Replace/Find'.Button(panel4.BoxSizer(wx. 'Incremental')) vbox3. size=(120. 'Whole Word')) grid. -1. 'Case Sensitive')) grid.Button(panel4. 0.Panel(panel. 9) # panel5 panel5 = wx. -1. 0. -1.Add(grid) vbox3.RB_GROUP style.GetBestSize()) line before the ShowModal() method. 1. otherwise all 4 RadioButtons would be mutually exclusive sizer22.Button(panel5. wx.CheckBox(panel3. -1))) sizer4. 1. 0.ALIGN_RIGHT) sizer5. A simple sketch of a more complex dialog or window might be handy.Button(panel4.Add(panel5.StaticBox(panel3.StaticBox(panel2. size=(50.Button(panel4.Add(wx. 'Replace All'. that we can divite it into five parts.Add(wx.Add(wx. 0.RB_GROUP)) sizer22. It will host all the five panels. that we have identified. -1. -1). wx. wx.Add(panel2.GridSizer(3. -1.Add(wx.Add(vbox. Together we have then 6 panels.Add(wx.Add(sizer22.TOP. 1. wx. -1.Add(wx. -1))) panel4. 'All'. Each part will be a unique wx. 9) # panel3 panel3 = wx.CheckBox(panel3. 5) panel.) Before we actually code our layout.Add((191. The first panel All five panels reside in one column.Destroy() app = wx. -1) sizer4 = wx. 'Close'. 1) panel2.BOTTOM. 'Wrap Search')) grid. -1. size=(120. -1.ShowModal() self.VERTICAL) vbox3 = wx.zetcode. we should have an idea of how we are going to achieve our goal.Panel(panel. 'Regular expressions')) sizer3. -1))) sizer4. -1.SetSizer(hbox2) vbox.SetClientSize(panel. -1))) sizer4.BOTTOM. 0.RadioButton(panel2.Add(wx.StaticBoxSizer(wx. 4) panel3.Centre() self.HORIZONTAL) sizer5.RadioButton(panel2. orient=wx.Add(wx. orient=wx.App() FindReplace(None.Add(wx.SetSizer(vbox_top) self.CheckBox(panel3. 5) http://www.Add(panel4. -1.SetSizer(sizer3) vbox. wx.VERTICAL) # we must define wx. -1.MainLoop() (Remark for Windows users.CheckBox(panel3. 5) grid.RIGHT. we clearly see.Add(wx. is a parent panel. 'Scope'). 1. 'Replace'.SetSizer(sizer5) vbox. 15) # panel4 panel4 = wx. 2.BOTTOM.Add(sizer21.Add(vbox3.StaticBoxSizer(wx. 'Options'). The close button will also have a separate panel. If we look at the dialog screenshot. -1. -1.Add(panel3. size=(120. put self. -1. wx.Add(wx.Layout management in wxPython hbox2. 2) sizer4.VERTICAL) grid = wx.Panel.Add(wx.BoxSizer(wx.LEFT. 'Selected Lines')) hbox2. 9) vbox_top. -1. 'Find/Replace') app. wx. size=(120. -1))) sizer4. '&File') self. 'Exit Calculator') menubar. size=(120. -1. 2.GridSizer lays out widgets in two dimensional table. wx.GridSizer will be explained in the next section. -1.MenuBar() file = wx. id. Well.BoxSizer. int vgap=0. int cols=0. Figure: GridSizer example #!/usr/bin/python # gridsizer. '&Quit'.Add(wx. title): wx.py import wx class GridSizer(wx. It is a job for wx.GridSizer is pretty straightforward. In our example we create a skeleton of a calculator. http://www.com/wxpython/layout/ wx.Button(panel4. 2) sizer4.BoxSizer-s we use wx. size=(120.GridSizer(int rows=1.GridSizer(2. 'Find'. sizer4 = wx.Button(panel4. id. int hgap=0) In the constructor we specify the number of rows and columns in the table. Those cells all have the same size and the same width. 2.Frame): def __init__(self.__init__(self. We need four buttons of the same size in a particular panel. Apart from wx. size=(300. parent.GridSizer-s as well. The since the usage of the wx. 'Replace'.SetMenuBar(menubar) 9 de 17 27/04/2008 1:03 .GridSizer is very useful.Add(wx.Button(panel4.Append(1.Button(panel4. there is not much to explain. 'Replace All'.Append(file. -1))) sizer4. since it organizes all widgets in a grid of cells.zetcode. And the vertical and horizontal space between our cells.GridSizer. 250)) menubar = wx. -1))) sizer4. -1.GridSizer wx. parent.Frame. size=(120. Each cell within the table has the same size. wx. -1))) In our example the wx. It is a perfect example for wx.Add(wx.Layout management in wxPython wx. 'Replace/Find'. title.Add(wx.GridSizer. -1. size=(120.Menu() file. FlexGridSizer suitable for such a task.Bind(wx. A developer can easily set up a dialog 10 de 17 27/04/2008 1:03 .TOP | wx. -1. 0.Button(self. 0.zetcode. 0. wx. (wx. -1.App() GridSizer(None.EXPAND | wx. All cells in wx.SetSizer(sizer) self. id=1) http://www.Button(self. 0. '7'). wx. 0.EXPAND).Button(self.TE_RIGHT) sizer.Button(self. 'Close'). '5'). wx.VERTICAL) self. 'Bck'). I find wx.EXPAND). 1.EXPAND). 0. '2').EXPAND). wx. -1. wx. wx. 0. -1. wx. '+'). -1. int vgap=0. -1. '/'). event): self. 0. vgap and hgap add some space between widgets in both directions. It does also lay out it's widgets in a two dimensional table. It is a convenience method for adding multiple widgets at one time. (wx. '6'). wx. (wx.TextCtrl(self. -1. '8'). wx. -1.display.Button(self. wx. 0. wx. The first row is filled first.display = wx. '9'). (wx. 0. wx. (wx.EXPAND) ]) sizer. (wx.EXPAND). 'GridSizer') app. '-'). (wx.FlexGridSizer(int rows=1.EXPAND). wx. 0. '*').Button(self. ''). -1. '='). 0. they are added. (wx. (wx. '0'). Such tricks are quite common.FlexGridSizer This sizer is similar to wx. wx. In our example we used the AddMany() method. All cells have the same width in a column. 0.EXPAND). 0.Button(self.Button(self.Button(self. wx. 0.EXPAND) self. -1.Button(self. -1. AddMany(list items) Widgets are placed inside the table in the order. It adds some flexibility to it.GridSizer(4.Add(self. -1.com/wxpython/layout/ sizer = wx.EXPAND).Button(self.AddMany( [(wx. (wx.Button(self. wx. 3.EXPAND).StaticText there.EXPAND). -1. wx. 0.EXPAND).BoxSizer(wx.Button(self.GridSizer.Button(self. -1. style=wx. (wx.EXPAND). '3'). 0. 0.EXPAND). ''. -1. (wx.EVT_MENU.EXPAND).Button(self.EXPAND). -1. (wx. 0. (wx.OnClose.EXPAND). (wx. (wx.Layout management in wxPython self. wx. 'Cls'). wx. -1.Add(gs. wx. -1. '. (wx.FlexGridSizer have the same height in a row.Button(self. '1').Button(self.Button(self. -1.EXPAND). 4) gs = wx. -1. wx. -1. 3) gs. -1. 0.Close() app = wx.Show(True) def OnClose(self. wx. But all rows and columns are not necessarily the same height or width. '4'). We simply put an empty wx. (wx.StaticText(self. self. (wx. 0. wx. wx. 4. wx.BOTTOM.Centre() self. Many times developers have to develop dialogs for data input and modification.').GridSizer cells are of the same size.MainLoop() Notice how we managed to put a space between the Bck and the Close buttons. int cols=0.EXPAND).EXPAND).Button(self. then the second row etc. int hgap=0) rows and cols specify the number of rows and columns in a sizer. Centre() self.EXPAND). 'Title') author = wx. (tc2. 25) title = wx. 1) We make the third row and second column growable. style=wx. 'Author') review = wx.EXPAND) in order to make it really work. 1. wx.AddMany([(title).Layout management in wxPython http://www. 'FlexGridSizer') app.AddGrowableCol(1.TE_MULTILINE) fgs.EXPAND).py import wx class FlexGridSizer(wx. wx. (tc3. 1) hbox.AddGrowableRow(2. wx. 1. 1. (tc2. wx. -1) tc2 = wx.ALL | wx.GridSizer share this method. 1) fgs.ALL | wx.Panel(self. It is also possible to accomplish this with wx. fgs.EXPAND). We must not forget to make the widgets expandable (wx. -1) hbox = wx.AddGrowableRow(2. (tc1.zetcode. -1. 15) We create a horizontal box sizer in order to put some space (15px) around the table of widgets.TextCtrl(panel.GridSizer. (author).App() FlexGridSizer(None. -1.BoxSizer(wx.FlexGridSizer(3. id.BoxSizer(wx.EXPAND)]) fgs.TextCtrl(panel.__init__(self. id.AddGrowableCol(1. wx. -1. wx. (tc3. because of the constraint that each cell has the same size.EXPAND).StaticText(panel. 1. title): wx.SetSizer(hbox) self.TextCtrl(panel. size=(290.StaticText(panel. the third one will grow in both direction.HORIZONTAL) fgs = wx.HORIZONTAL) . wx. 1) fgs.Show(True) app = wx. The first two text controls will grow in horizontal direction. title. #!/usr/bin/python # flexgridsizer. parent. when the window is resized.EXPAND. (review. 1. Both wx. 1.Add(fgs. hbox. (tc1.MainLoop() hbox = wx. -1.EXPAND)]) We add widgets to the sizer with the AddMany() method. 1.FlexGridSizer and wx. 1. -1) tc3 = wx.Add(fgs. 1. but it would not look nice. wx.com/wxpython/layout/ window with this sizer. (review. wx.Frame. 1. (author). 11 de 17 27/04/2008 1:03 .StaticText(panel. 9. fgs. wx.. This way we let the text controls grow. 'Review') tc1 = wx. parent. 15) panel.Frame): def __init__(self.. 2. 250)) panel = wx.EXPAND.AddMany([(title).EXPAND). -1.EXPAND). integer hgap) The vertical and the horizontal gap defines the space in pixels used among all children.DefaultSpan.com/wxpython/layout/ Figure: FlexGridSizer example wx. Believe me. 2) spans a widget across 3 rows and 2 columns. If you want your items to grow and shrink. e. All we have to do is to create several layouts with it. wx. There are more difficult things in programming. Items can also optionally span more than one row and/or column. pos specifies the position in the virtual grid. tuple pos. you can use these two methods.Layout management in wxPython http://www. span of (3. integer border=0.GridBagSizer has a simple constructor. Many programmer find it difficult to use. The topleft cell has pos of (0. flag and border were discussed earlier by wx. We can find it in other toolkits as well.GridBagSizer(integer vgap. The items in the grid can change their size or keep the default size. wx. AddGrowableRow(integer row) AddGrowableCol(integer col) Rename dialog 12 de 17 27/04/2008 1:03 . userData=None) Item is a widget that you insert into the grid. span is an optional spanning of the widget. This kind of sizer is not typical only for wxPython. integer flag=0. Even though it is more complicated.BoxSizer. We add items to the grid with the Add() method. when the window is resized. There is no magic in using this sizer. 0). Add(self. item. Find This sizer enables explicit positioning of items. Play with it a bit.zetcode. certainly not rocket science.GridBagSizer The most complicated sizer in wxPython.g. tuple span=wx. it is all the quirks. 5).App() Rename(None. Plus we put 5 pixels of space to the left and to the right of the widget. id.EXPAND | wx. wx. (0. (1. 4). 5) The wx. title. Notice that once we apply some 13 de 17 27/04/2008 1:03 . -1. title): wx.BOTTOM. 3)) sizer. text = wx. so that we have some space between the wx.TextCtrl goes to the beginning of the second row (1. #!/usr/bin/python # rename.TextCtrl(panel.EXPAND | wx.Frame): def __init__(self.MainLoop() We must look at the dialog window as a one big grid table. In our example. 5) buttonOk = wx.Button-s. one wx.Add(buttonClose. tc = wx.BOTTOM. 28)) buttonClose = wx. we will create a rename dialog.BOTTOM. 0).__init__(self.Add(buttonOk. border=5) The text 'Rename to' goes to the left upper corner. 0). (1. (3. it's logic. left and bottom. -1. id. It expands 1 row and 5 columns. border=5) tc = wx. (1. size=(320.Layout management in wxPython http://www. border=5) We put two buttons into the fourth row. The third row is left empty. There is no need to be afraid of wx.com/wxpython/layout/ Figure: Rename window The first example is intentionally a very simple one.LEFT | wx. Remember.LEFT | wx.RIGHT | wx.AddGrowableRow(2) panel.GridBagSizer(4.Button(panel.StaticText(panel. (3. 'Ok'.LEFT | wx.RIGHT. border=5) sizer. So we specify the (0.Button(panel. -1.RIGHT.Panel(self.Add(tc. flag=wx.zetcode. -1. 'Rename To') sizer. -1) sizer = wx. flag=wx.SetSizerAndFit(sizer) self. 0) position.Add(text. 3)) sizer.TextCtrl and the buttons. that we count from zero.StaticText(panel.StaticText. parent. (3. wx. parent.BOTTOM. 'Rename Dialog') app. 'Rename To') sizer. Once you understand It will have one wx. flag=wx. 4) text = wx. flag=wx.Centre() self. sizer. -1) sizer.Add(tc. size=(90. -1) sizer.RIGHT | wx. 'Close'.TOP | wx. (0.Add(buttonClose.py import wx class Rename(wx. size=(90. 28)) sizer.GridBagSizer. 130)) panel = wx.Add(text. Plus we add some space to the bottom. 0). 0). 4).AddGrowableCol(1) sizer. -1. We put the ok button into the fourth column and the close button into the fifth one. 5).TextCtrl and two wx.Add(buttonOk.TOP | wx.Show(True) app = wx. it is quite simple to use it. (1. So that it could be easily understood. 5).Frame. (1. (3.LEFT | wx. 0).TextCtrl(panel. Frame): def __init__(self. title.GridBagSizer. A careful reader might notice. id. In the constructor of the already.Layout management in wxPython http://www. e. column and the third row growable. we did not put any space to the right of the ok button. Try to window. 500)) panel = wx. This example will show a layout of a very handy dialog which you can find in Figure: Open Resource window #!/usr/bin/python # openresource.g.com/wxpython/layout/ space to one widget. it is applied to the whole row. parent. title): wx. -1.__init__(self. Open Resource The next example will be a bit more complicated.StaticText(panel.zetcode. is to make our dialog resizable. So there is some space sizer. parent. Now we can expand or shrink our window. or to the right of the close button. 4) text1 = wx. that we did not specify any space between the two buttons. We will create an Open Resource Eclipse IDE.GridBagSizer(4. That's why I did not specify bottom space for the ok button.AddGrowableRow(2) The last thing we must do. -1) sizer = wx.Panel(self. We make the second comment those two lines and see what happens. we put some space between all widgets.AddGrowableCol(1) sizer. size=(400.py import wx class OpenResource(wx. wx. id.Frame. 'Select a resource to open') 14 de 17 27/04/2008 1:03 . Add(buttonOk. style=wx.NO_BORDER) sizer. (1. 0). 3).Show(True) app = wx.Add(text2. 3).LB_ALWAYS_SB) sizer. -1. (9. border=5) list2 = wx.py example is a type of a window. -1. 5) text3 = wx. -1. (14.zetcode. 1)) sizer. It is a dialog window for creating a new class in Java.LEFT | wx.Add(text1. 3). -1) sizer.BOTTOM.LEFT | wx. flag=wx. 0). 0).RIGHT. flag=wx. 0). -1. (2.AddGrowableCol(0) sizer.Add(buttonCancel.TOP | wx.EXPAND | wx. (8.Button(panel.ListBox(panel. 'Open Resource') app.LEFT | wx. So we make the first row of each wx.BOTTOM.TextCtrl(panel.AddGrowableRow(3) sizer. 5)) panel. border=5) sizer.AddGrowableRow(3) sizer. 5) cb = wx.LEFT | wx. 0). wx.LEFT | wx.LB_ALWAYS_SB) sizer.png'). 0).LEFT | wx. 0). border=5) tc = wx. Create new class newclass. (14.CheckBox(panel.Centre() self. 2).Add(list2. 'OK'. flag=wx.EXPAND | wx. wx.Add(help.ListBox growable.StaticText(panel.Button(panel.SetSizer(sizer) self. 'Show derived resources') sizer.Bitmap('icons/help16. that I found in JDeveloper.Layout management in wxPython http://www.TOP | wx.com/wxpython/layout/ sizer. (5. size=(90. size=(90. (1. 28)) buttonCancel = wx. 28)) sizer.RIGHT. (3. (3. 'Cancel'.MainLoop() sizer.RIGHT | wx.LEFT. -1.StaticText(panel. (14. -1. flag=wx. border=5) list1 = wx. (12.Add(tc. wx. -1. border=5) buttonOk = wx. style=wx.Add(list1. 0).AddGrowableRow(9) sizer.Add(cb.RIGHT.BOTTOM. -1. 'Matching resources') sizer.ListBox-es growable.ListBox(panel.App() OpenResource(None. -1. flag=wx. 'In Folders') sizer. style=wx.TOP | wx. 15 de 17 27/04/2008 1:03 . wx. 5) text2 = wx. (0.Add(text3. border=5) help = wx.BitmapButton(panel.SetEmptyCellSize((5. flag=wx.RIGHT.EXPAND | wx.AddGrowableRow(9) We want to have both wx.BOTTOM.LEFT | wx. Button(panel. 0. 5) boxsizer.__init__(self.EXPAND. (1.'.Frame. -1. 0). wx.StaticLine(panel. id. 30)) sizer. -1. 1).TOP | wx.Add(combo. (2. 5) button2 = wx.GridBagSizer(0. (7. wx. (4. 'Java Class') sizer. 30)) sizer.StaticBitmap(panel.TOP. size=(-1.Frame): def __init__(self. -5) text3 = wx. wx. 3). (7.SetSizer(sizer) self.Add(button3.LEFT | wx.RIGHT . wx. 10) button3 = wx.TextCtrl(panel. 0).Bitmap('icons/exec. 1).LEFT | wx. wx.TOP | wx. (1. 1).Add(button2.StaticText(panel. 4). 'Optional Attributes') boxsizer = wx.Add(tc1.. (0. flag=wx. (0.'.StaticText(panel. -1. (4.LEFT. 0) text1 = wx. size=(-1.Fit(self) panel. 3). border=45) line = wx. 0). wx. (3. wx. 1). wx. 1).zetcode. 3).png')) sizer. wx.Add(wx.Layout management in wxPython http://www. (1.StaticText(panel.LEFT | wx. -1. 'Name') sizer. parent.Add(wx.LEFT. size=(-1. wx.py import wx class NewClass(wx. 0).LEFT | wx.LEFT | wx. title): wx. 4). title) panel = wx. -1.LEFT | wx.LEFT. 1).CheckBox(panel.ComboBox(panel. -1. ) sizer.TOP | wx. 0).. -1.EXPAND. (1. -1. border=10) combo = wx.VERTICAL) boxsizer.Add(tc2.Add(text1. border=10) tc2 = wx.EXPAND.RIGHT.BOTTOM. size=(-1.Add(text2. 10) sizer. 1). 4).StaticText(panel. 'Browse. 'Cancel'. 'Ok'.TOP. flag=wx. flag= wx.Button(panel. 0). (1.Add(text3. (1. 5) sizer.Add(text4.LEFT | wx.StaticBoxSizer(sb. wx. -1. border=10) tc1 = wx.CheckBox(panel. wx. 0. (1. 10) button5 = wx. wx. 5). 'Generate Default Constructor'). (4. 0. 'Generate Main Method'). 'Public'). flag=wx.BOTTOM | wx. (1.Button(panel. -1.LEFT | wx. parent. size=(-1. -15) text2 = wx. (3. 1).RIGHT .LEFT.BOTTOM.AddGrowableCol(2) sizer. (5. 5) text4 = wx.RIGHT . -1) sizer. 'Package') sizer.Panel(self. 0).Add(icon. 'Extends') sizer. 3). 5).Centre() self. -1. (2.TOP | wx. (1.TOP | wx. 'Browse. -1) sizer = wx. 10) button4 = wx. wx.LEFT. 5) boxsizer. 30)) sizer.TOP | wx. -1.App() 16 de 17 27/04/2008 1:03 .Add(button1.Add(wx. 30)) sizer.Show(True) app = wx.Button(panel.com/wxpython/layout/ Figure: new class window #!/usr/bin/python # newclass.LEFT.Add(button4. 4). (1.EXPAND.StaticBox(panel. (3.CheckBox(panel..EXPAND | wx. border=15) icon = wx.Button(panel. -1. flag=wx.Add(boxsizer. id.Add(button5.TOP | wx. (7. 'Help'. 30)) sizer. size=(-1.Add(line. (1.TextCtrl(panel. 5) button1 = wx. -1 ) sizer. wx. 5) sb = wx.TOP | wx. -1. -1. -1. 30)) sizer.TOP | wx.. png')) sizer. If we call Fit() method. sizer. (1.Add(icon.Layout management in wxPython NewClass(None. wx.StaticBitmap into the first row of the grid. icon = wx. Print converter TT-Solutions wxWidgets (wxWindows) consulting and development. We could use wx. We would get the same result. 4). wx. 2007 © 2007 Jan Bodnar 17 de 17 27/04/2008 1:03 .BOTTOM with border 15.zetcode. the size of what happens.EXPAND.TOP | wx. -15) Notice. 'Create Java Class') app. free.StaticLine(panel.Add(line. flag=wx. Ask the wxExperts! Home ‡ Contents ‡ Top of Page ZetCode last modified June 3. border=45) We put an wx. -1. 5). (0. By using images we can make our applications look better.Bitmap('icons/exec. Try to comment this line and see Free XML (XSL) tutorial.Fit(self) We did not set the size of the window explicitly.LEFT. that we have used negative number for setting the top border. (1.com/wxpython/layout/ line = wx.MainLoop() http://www. XML/XSL to PDF. 0).StaticBitmap(panel. -1 ) sizer. -1. samples. XSL Tutorial. Light. We place it on the right side of the row. the window will exactly cover all widgets available. that has been with an event handler. generated. So when we call MainLoop() method. The MainLoop() Definitions Event is a piece of application-level information from the programming construct that waits for and dispatches events or messages in a program.MoveEvent. An application reacts to different event types which are generated during it's life. A move event is generated. Services. internet connection. Debugger. when we move a window to a new this event is wx.Events in wxPython http://www. e.EVT_MOVE position.com/wxpython/events/ Python IDE Faster. EasierContents Home Python Development Editor. A dispatcher is a process which maps Event object is an object associated with the event. It is usually a window. that binds an event type A simple event example In the following section we will describe a simple event. Event binder is an object. The event binder for #!/usr/bin/python # moveevent. Event type is a unique event. Browser. typically the GUI toolkit. Events are generated mainly by the user of an application. Event handlers are methods that events to process them. The event loop repeatedly looks for underlying framework. Ruby. window manager. Conseil TDD. Event loop is a react to events. C++.zetcode. The event type is wx. But they can be generated by other means as well. and more Scrum Formation. Java J2EE. our application waits for events to be generated.g. All GUI applications are event-driven.py 1 de 14 27/04/2008 1:03 . We will talk about a move event. timer. Python Events in wxPython Events are integral part of every GUI application. method ends when we exit the application. events to event handlers. (10.Show(True) def OnMove(self.EVT_MOVE event binder to the OnMove() method.Frame): def __init__(self. y = event.st1. self. We can find out the current position by calling the GetPosition() 2 de 14 27/04/2008 1:03 . 30)) self.Bind(wx. This object holds information about the window.GetPosition() self. In our case the Event object is the wx. title. size=(250. (30.StaticText(self.StaticText(self. For example the Event object or the position of the of a wx. parent.EVT_MOVE.com/wxpython/events/ import wx class MoveEvent(wx. -1.__init__(self. self. parent. id.OnMove) Here we bind the wx.App() MoveEvent(None.GetPosition() The event parameter in the OnMove() method is an object specific to a particular event type. self. (10.SetLabel(str(x)) self.st1 = wx.30)) self.Centre() self. y = event. (30.MoveEvent class. event): x.Frame widget. title): wx.Events in wxPython http://www. 180)) wx. method of the event.OnMove) self. id. 'x:'. -1.10)) wx.zetcode. def OnMove(self.st2.Bind(wx.MainLoop() The example displays the current position of the window. event): x.st2 = wx. ''.SetLabel(str(y)) app = wx. 'move event') app. ''. -1.StaticText(self.StaticText(self.Frame. 10)) self. -1.EVT_MOVE. In our case it is the instance event. 'y:'. -1. id2 is used when it is desirable to bind a handler to a range of ids.Window inherits. when an event is generated Bind an event to an event handler.ID_ANY. source=None.com/wxpython/events/ Figure: move event Event binding Working with events is straightforward in wxPython. There are three steps: Identify the event binder name: wx. If 3 de 14 27/04/2008 1:03 . it is a method. that is called. id2=wx. that a programmer binds to an event. It is a method. id=wx. The id is used to differentiate among them. handler is an object to be called. It specifies the type of the event. Note that method Bind() is defined in class EvtHandler. It is the class. handler. wx.Window is a base class for most widgets in wxPython. such as with EVT_MENU_RANGE. menu items etc. wx. In other words. Sometimes a word hook is used. The method has the following parameters: Bind(event.Events in wxPython http://www. id parameter is used.EVT_SIZE.EVT_CLOSE etc Create an event handler. You bind an event by calling the Bind() method. source parameter is used when we want to differentiate between the same event type from different widgets. There is also a reverse process.ID_ANY) event is one of EVT_* objects. from which wx.zetcode. when we have multiple buttons. In wxPython we say to bind a method to an event. MessageDialog(None.Centre() self.MessageDialog(None. we must bind the wx.ShowModal() 4 de 14 27/04/2008 1:03 . parent. It has the same paremeters as the above one.EVT_CLOSE. we process a wx. we call the method Veto(). -1. To do this. dial = wx. In many applications.ShowModal() if ret == wx. id. self.CloseEvent.Bind(wx.__init__(self. if we made some changes. This event is called.ICON_QUESTION) ret = dial.Frame.NO_DEFAULT | wx. 'Are you sure to quit?'. To do this.ID_YES: self.Veto() app = wx. when we click the X button on the titlebar. Vetoing events Sometimes we need to stop processing an event. 200)) self. we call the Unbind() method.Destroy() else: event.Show(True) def OnClose(self.App() Veto(None. 'Question'. event): dial = wx.YES_NO | wx. parent.YES_NO | wx. title.NO_DEFAULT | wx. title): wx. 'Are you sure to quit?'. press Alt + F4 or select close from the system menu.zetcode. size=(250. 'Veto') app.Frame): def __init__(self. wx.MainLoop() In our example. wx. 'Question'.py import wx class Veto(wx.Events in wxPython http://www. we want to prevent from accidentally closing the window.OnClose) self.EVT_CLOSE event binder. #!/usr/bin/python # veto.ICON_QUESTION) ret = dial.com/wxpython/events/ we want to unbind a method from an event. id. we must call the up in an endless cycle. parent.Button. we would end Event propagation There are two types of events. the event that is catched in a event handler stops method. parent. pos): wx. id): wx.ID_YES: self. By calling the Close() method.EVT_BUTTON. self. parent. Notice that to close the window. They differ in propagation. It does not make sense for this event to propagate to parent widgets. propagating. id.Panel.Destroy() else: event. Destroy() method. Event propagation is travelling of events from child widgets to parent widgets and grand parent widgets etc.py import wx class MyPanel(wx. or veto the event. By default. id) self. Command events do propagate.Button): def __init__(self.Events in wxPython http://www. we show a message dialog. we must call the Skip() #!/usr/bin/python # propagate.OnClicked) def OnClicked(self.__init__(self.Veto() Depending on the return value. label. pos) 5 de 14 27/04/2008 1:03 . To continue propagation.CloseEvent is a basic event. Basic events and command events.zetcode.Skip() class MyButton(wx.__init__(self. For example wx. label. id.Bind(wx. Basic events do not propagate. we destroy the window. parent. if ret == wx.Panel): def __init__(self. event): print 'event reached panel class' event.com/wxpython/events/ During the close event. EVT_BUTTON.Events in wxPython http://www. self. window identity in the event system. event reached button class event reached panel class event reached frame class We get this. title): wx.Show(True) def OnClicked(self. when we click on the button. 'Ok'.Skip() app = wx.EVT_BUTTON.App() Propagate(None. event): print 'event reached button class' event. id.Skip() class Propagate(wx. 150)) panel = MyPanel(self.OnClicked) self. -1. self. title. parent. we have a button on a panel.com/wxpython/events/ self. Try to omit some Skip() methods and see.Centre() self. what hapens.Bind(wx. Window identifiers Window identifiers are integers that uniquely determine the create window id's.__init__(self.Frame): def __init__(self. The panel is placed in a frame widget. 'Propagate') app. (15.Bind(wx. The event travels from the button to panel and to frame.Frame.OnClicked) def OnClicked(self. -1) MyButton(panel. size=(250.zetcode. 15)) self.MainLoop() In our example. event): print 'event reached frame class' event. We define a handler for all widgets. -1. parent. There are three ways to let the system automatically create an id use standard identifiers create your own id 6 de 14 27/04/2008 1:03 . id. -1. title): wx. title.Panel(self.OnExit. self.__init__(self. We usually use this option when we do not need to change the widget state. The automatically created id's are always negative. parent. parent. self.ID_ANY for the id parameter. id=exit.GetId()) app = wx. that will never be changed during the life of the application.com/wxpython/events/ Each widget has an id parameter. 100)) panel = wx. We will determine the id for us. wx. -1) exit = wx. event): self.Events in wxPython http://www. (10.GetId()) We get the automatically generated id by calling the GetId() method. If we work with multiple widgets.OnExit.Frame): def __init__(self. For example a static text.Show(True) def OnExit(self. 10)) self.Bind(wx.Frame.py import wx class AuIds(wx. id.Button(parent. can still get the id.Centre() self. id=exit. -1.Button(parent.Bind(wx. self.zetcode.ID_ANY) If we provide -1 or wx. -1) wx. There is a method GetId(). whereas user specified id's must always be positive. '') app. wx. which #!/usr/bin/python # automaticids. if we want. we do not care about the actual id value.EVT_BUTTON.MainLoop() In this example.EVT_BUTTON. This is a unique number in the event system.Close() self. size=(170. 'Exit'. we must differantiate among them. we let the wxPython automatically create an id for us.Button(panel.App() AuIds(None. 7 de 14 27/04/2008 1:03 . id. Close() app = wx. wx.LEFT.Show(True) def OnQuit(self. 0. event): self.Button(panel. 9).AddMany([(wx.TOP. 0.Frame. wx. id.__init__(self. '') app. title. (wx. parent. wx.Panel(self.Button(panel.zetcode. 2) grid. The some platforms.LEFT. (wx.Events in wxPython http://www.ID_SAVE).App() Identifiers(None.ID_EXIT)).SetSizer(grid) self. 8 de 14 27/04/2008 1:03 .ID_EXIT) panel. 9).ID_STOP).Button(panel.MainLoop() In our example we use standard identifiers on buttons.TOP | wx.com/wxpython/events/ Standard identifiers should be used whenever possible. wx. -1. parent.ID_CANCEL).LEFT. (wx. wx. (wx.Button(panel. self. id.Button(panel. wx.ID_NEW))]) self.ID_DELETE). wx.OnQuit. 9). 9). 150)) panel = wx.Frame): def __init__(self. 0. identifiers can provide some standard graphics or behaviour on #!/usr/bin/python # identifiers. On linux. size=(200. -1) grid = wx. 0.Button(panel.Bind(wx. wx. title): wx.GridSizer(3.Centre() self. wx.py import wx class Identifiers(wx. wx. the buttons have small icons. (wx.EVT_BUTTON. id=wx. Pen(self. y) def OnSize(self. The focus is changed by clicking or by a keybord key. We define our own global ids. Usually Tab/Shift+Tab.Refresh() def OnSetFocus(self.Panel): def __init__(self.Bind(wx.EVT_SIZE.Bind(wx.Panel. event): self. There are two event is generated when a widget receives focus. event): self.OnPaint) self. self. y = self. which has the focus. 0.PaintDC(self) dc. #!/usr/bin/python # focusevent.color)) x. parent): wx. The wx.EVT_PAINT.Bind(wx.EVT_KILL_FOCUS is generated.color = '#0099f7' self. self. event): dc = wx.__init__(self.OnSetFocus) self. self.Bind(wx. self. -1) self.zetcode. is sent to the widget.GetSize() dc.py import wx class MyWindow(wx.Events in wxPython http://www. parent.Refresh() 9 de 14 27/04/2008 1:03 .EVT_SET_FOCUS. Miscellaneous events Focus event The focus indicates the currently selected widget in application.OnSize) self.EVT_KILL_FOCUS. when the widget looses focus.SetPen(wx. The The text entered from the keyboard or pasted from the clipboard types concering focus.com/wxpython/events/ Figure: standard identifiers The last option is to use own identifiers.DrawRectangle(0. which wx.color = '#b3b3b3' self. x.EVT_SET_FOCUS event.OnKillFocus) def OnPaint(self. EXPAND|wx. 9). The panel with focus is highlighted. 'focus event') app.Frame. id.SetSizer(grid) self.LEFT.TOP|wx.com/wxpython/events/ def OnKillFocus(self. when we click on a built in Scrollbar. parent. (MyWindow(self). For stand-alone Scrollbars. wx.ScrollWinEvent.GridSizer(2.Frame): def __init__(self. Figure: focus event ScrollEvent The following code is an example of a wx.Centre() self.__init__(self.Events in wxPython http://www. title): wx. wx. wx.BOTTOM|wx.RIGHT. 9).EXPAND|wx.RIGHT. 10) grid.MainLoop() In our example. we have four panels. 1. 10.AddMany([(MyWindow(self). (MyWindow(self).App() FocusEvent(None. This Scrollbar is activated with the SetScrollbar() method call. namely event is generated.EXPAND|wx. -1. parent. 1.Refresh() class FocusEvent(wx.BOTTOM|wx. (MyWindow(self). event): self. title. 1. size=(350.EXPAND|wx.zetcode. Built-in 10 de 14 27/04/2008 1:03 .color = '#b3b3b3' self.LEFT. 9)]) self. wx.9). id.TOP|wx. 2.Show(True) app = wx. 250)) grid = wx. there is another event type. 1. self.GetPosition() self.SetLabel(str(y)) app = wx. when our window is resized.VERTICAL. 1. parent.ScrollEvent.Centre() self. id. http://www.Show(True) def OnSize(self.EVT_SIZE.__init__(self. we show the size of the window in the titlebar. In our example.EVT_SCROLLWIN.OnScroll) panel.Frame. title): wx.Frame): def __init__(self.com/wxpython/events/ #!/usr/bin/python # myscrollwinevent. 50).Frame): def __init__(self. self. -1. 0.zetcode.MainLoop() SizeEvent A wx.py') app.py import wx class ScrollWinEvent(wx. 'scrollwinevent.__init__(self.Panel(self. #!/usr/bin/python # sizeevent. id. 'sizeevent.Centre() self. id. parent.Frame. (30.Events in wxPython wx.StaticText(panel.py import wx class SizeEvent(wx. title) self.App() ScrollWinEvent(None.MainLoop() 11 de 14 27/04/2008 1:03 . id.0)) panel.SetScrollbar(wx. evt): y = evt.GetSize())) app = wx. self.OnSize) self. '0'.st.App() SizeEvent(None.st = wx.SizeEvent is generated. 6. parent. -1. title) panel = wx. title): wx.Bind(wx.py') app. event): self.Show(True) def OnScroll(self. parent.Bind(wx. -1) self.SetTitle(str(event. count + 1 print self.com/wxpython/events/ self. title): wx. happens when we resize a window or when we maximize it. Figure: sizeevent.Frame): def __init__(self.Events in wxPython http://www. Note that when we minimize a window.Bind(wx.SetTitle(str(event. we call the GetSize() method of the event object.__init__(self. For example.Show(True) def OnPaint(self. id.zetcode.count = 0 self.count = self.Frame. id. self.EVT_PAINT. parent. parent. This paint event can be generated programatically as well. when we call SetLabel() method to change a paint event is generated.OnPaint) self.GetSize())) To get the current size of the window. event): self. no #!/usr/bin/python # paintevent.count 12 de 14 27/04/2008 1:03 .StaticText widget.py PaintEvent A paint event is generated when a window is redrawn. title) self.py import wx class PaintEvent(wx.Centre() self. A wx. NO_DEFAULT. This event is sent to the widget that has currently A common request is to close application. id.GetKeyCode() if keycode == wx. -1. -1) panel. event): keycode = event.SetFocus() self.KeyEvent is focus.py import wx class KeyEvent(wx.Events in wxPython http://www.Close() event.Centre() self.WXK_ESCAPE: ret = wx.zetcode.App() KeyEvent(None.EVT_KEY_UP wx.Frame. title): wx.YES_NO | wx. id. title) panel = wx.py') app.Bind(wx. There are three different key handlers: wx.EVT_KEY_DOWN wx.EVT_KEY_DOWN.__init__(self. #!/usr/bin/python # keyevent. parent. KeyEvent When we press a key on our keyboard.MessageBox('Are you sure to quit?'.Panel(self.YES: self.OnKeyDown) panel. self. 'Question'. 'keyevent.MainLoop() In our example we print the number of paint events generated into the console. 'paintevent.py') app. when Esc key is pressed. parent. wx.Show(True) def OnKeyDown(self.EVT_CHAR generated. self) if ret == wx.MainLoop() 13 de 14 27/04/2008 1:03 .com/wxpython/events/ app = wx. -1. wx.Skip() app = wx.Frame): def __init__(self.App() PaintEvent(None. The Esc key has wx.com/wxpython/events/ keycode = event. Cookbook Bind Print & Bind Your Cookbook at Home.GetKeyCode() Here we get the key code of the pressed key.WXK_ESCAPE: We check the key code. Python Purse on sale Genuine python handbags on sale We Custom make handbag for you Home ‡ Contents ‡ Top of Page ZetCode last modified June 28.zetcode. if keycode == wx.WXK_ESCAPE code. Bind Kit Turns Recipes into a Book.Events in wxPython http://www. 2007 © 2007 Jan Bodnar 14 de 14 27/04/2008 1:03 . zetcode. title) wx.Centre() self. 'MessageDialog') app. parent. modify data. parent.FutureCall calls a method after 5 seconds.__init__(self. The second parameter is a method to be called. title): wx. Browser.FutureCall(5000. id. Easier Python Development Editor. id.ShowMessage) self. VB & C# sample wxPython dialogs Dialog windows or dialogs are an indispensable part of most modern GUI applications. after which a given method is called. Dialogs are program. A dialog is defined as a conversation between two or more persons.Frame): def __init__(self. When a cd is finished burning. self. change the application settings etc. a #!/usr/bin/python # message.FutureCall(5000. The first parameter is in milliseconds. A good message box pops up.py import wx class MessageDialog(wx. and more Message Box for ASP. 'Info') app = wx. Debugger. self.Frame.Show(True) def ShowMessage(self): wx.wxPython dialogs http://www.NET Modal message box/dialog for Web Fully customizable. a time value. -1.com/wxpython/dialogs/ Home Contents Python IDE Faster.MessageBox('Download completed'. important means of communication between a user and a computer A Simple message box A message box provides short information to the user.MainLoop() wx. A dialog is used to input data. In a computer application a dialog is a window which is used to "talk" to the application. example is a cd burning application. The parameter is 1 de 11 27/04/2008 1:04 .App() MessageDialog(None.ShowMessage) wx. MessageBox('Download completed'. These are dialogs for loading and saving files etc.com/wxpython/dialogs/ def ShowMessage(self): wx.YES_NO show Ok button show Cancel button show Yes. common programming tasks like showing text. The text message. Message dialogs Message dialogs are used to show messages to the user.Window parent.wxPython dialogs http://www. We provide three button. No buttons 2 de 11 27/04/2008 1:04 . receiving input . that we saw in the buttons that will be shown in a dialog. 'Info') wx.OK wx. previous example. We can change icons and wx.MessageBoxCaptionSt long style=wx.CANCEL wx.CENTRE. wx. They are customizable. -1)) flag meaning wx.MessageDialog(wx. string message.CANCEL | wx. parameters. They are more flexible than simple message boxes.zetcode.OK | wx.MessageBox shows a small dialog window. the title message and finally the Figure: A message dialog Predefined dialogs wxPython has several predefined dialogs. string caption=wx.Point pos=(-1. event): dial = wx.ShowMessage1) self.com/wxpython/dialogs/ wx.Frame. title): wx.ShowMessage3) self.ICON_INFORMATION wx. 'Error loading file'. event): dial = wx.ShowModal() 3 de 11 27/04/2008 1:04 . 2. id. 2. 'Question'.SetSizer(hbox) btn1. wx.EVT_BUTTON.EVT_BUTTON. parent. wx.EVT_BUTTON.MessageDialog(None. event): dial = wx. 150)) panel = wx.zetcode.__init__(self.Button(panel. btn2. -1.Bind(wx. 'Are you sure to quit?'.Button(panel. btn2. 'Error'. -1.ICON_ERROR) dial. btn3. wx.ICON_QUESTION) dial. self. -1.OK) dial.Add(sizer. title.ShowMessage4) def ShowMessage1(self.EVT_BUTTON. wx.ShowMessage2) self. size=(250. 'Info') 'Error') 'Question') 'Alert') sizer.YES_DEFAULT wx.OK | wx.MessageDialog(None.Button(panel. -1) hbox = wx. wx.BoxSizer() sizer = wx.ShowModal() def ShowMessage3(self.ICON_ERROR show an info icon show a question icon #!/usr/bin/python # messages.GridSizer(2. wx. 0.MessageDialog(None.Frame): def __init__(self. 'Download completed'. 2) btn1 btn2 btn3 btn4 = = = = wx.Bind(wx. 'Info'.NO_DEFAULT | wx.NO_DEFAULT wx. btn4]) hbox.ICON_ERROR wx.AddMany([btn1.Bind(wx.YES_NO | wx.ICON_HAND wx.py import wx class Messages(wx. 15) panel.wxPython dialogs http://www.Button(panel.Show(True) self.ICON_EXCLAMATION wx.ShowModal() def ShowMessage2(self.ICON_QUESTION make Yes button the default make No button the default show an alert icon show an error icon same as wx. btn3.Centre() self. -1.ALL. id.Bind(wx. wx. btn4. parent.Panel(self. ShowModal() The creation of the message dialog is simple.ShowModal() app = wx. The two strings and an error icon by specifying the wx. To show the dialog on screen. 'Error loading file'.wxPython dialogs http://www.ICON_ERROR provide the message text and the dialog title.com/wxpython/dialogs/ def ShowMessage4(self. event): dial = wx.App() Messages(None.MessageDialog(None. 'Exclamation'.MessageDialog(None. 'Messages') app.OK and wx.MainLoop() In our example. 'Unallowed operation'. -1.ICON_EXCLAMATION) dial. wx.ICON_ERROR) dial.OK | wx.OK | wx. We show an ok button flags. we have created four buttons and put them in a grid sizer.zetcode. We set the dialog to be a toplevel window by providing None as a parent. 4 de 11 27/04/2008 1:04 . We create them by specifying different style flags. we call the ShowModal() method. wx. dial = wx. These buttons will show four different dialog windows. 'Error'. These days most of these boxes provide additional information about the authors. Some of the more capable about boxes show animation. They also provide information about the application licence.zetcode. These boxes can show the logo of the company or the application logo. These methods are self-exlanatory.AboutDialogInfo() We will call the following methods upon a wx. about dialog box we must create two objects. A wx. these dialogs used to be quite brief. They give credits to additional programmers or documentation writers. In order to create an and a wx.x series.8.AboutDialogInfo wx.AboutBox. It is usually placed in the Help menu.Icon icon) SetWebSite(string URL) SetLicence(string licence) set the name of the program set the version of the program set the description of the program set the copyright fo the program set the licence of the program set the icon to be show set the website of the program set the licence of the program 5 de 11 27/04/2008 1:04 . Method Description SetName(string name) SetVersion(string version) SetDescription(string desc) SetCopyright(string copyright) SetLicence(string licence) SetIcon(wx.wxPython dialogs http://www.com/wxpython/dialogs/ About dialog box Almost every application has a typical about dialog box. 2.AboutDialogInfo object in our example. The purpose of this dialog is to give the user the basic information about the name and the version of the application. wxPython has a special about dialog box starting from But it makes a programmer's life easier. In the past. The dialog box is located in the Misc module. It is not rocket science to make such a dialog manually. wx. id=ID_ABOUT) menubar.Menu() help. wx. GTK+ can show all these fields.Frame. It is advised to provide licence possible.Python will show a native dialog. title. Features include powerful built-in editor. title): wx.zetcode. file comparison. """ licence = """File Hunter is free software. id. extensive archive handling and more. Otherwise it information in a separate menu item. if we want to stay as native as #!/usr/bin/python # aboutbox.wxPython dialogs http://www.py import wx ID_ABOUT = 1 class AboutDialogBox(wx. It can be a native dialog cannot display custom icons.Bind(wx.SetMenuBar(menubar) self.Append(help. 200)) menubar = wx.AboutDialogInfo as a parameter.AboutDialogInfo info) wxPython can display two kinds of About boxes.AboutBox is as follows.MenuBar() help = wx. parent. Windows native about dialog box platform we use and which methods we call.Append(ID_ABOUT. event): description = """File Hunter is an advanced file manager for the Unix operating system. these three fields.Show(True) def OnAboutBox(self. powerful batch renaming.Centre() self.AboutBox(wx.OnAboutBox. It depends on which or a wxPython generic dialog.EVT_MENU. It takes a wx. '&Help') self. you can redistribute it and/or modif 6 de 11 27/04/2008 1:04 .com/wxpython/dialogs/ AddDeveloper(string developer) AddDocWriter(string docwirter) AddArtist(string artist) AddTranslator(string developer) add a developer to the developer's list add a docwriter to the docwriter's list add an artist to the artist's list add a developer to the translator's list The constructor of the wx. self.__init__(self. size=(260. licence text nor the url's.Frame): def __init__(self. '&About') self. parent. If we omit will resort to a generic one. id. advanced search capabilities. SetCopyright('(C) 2007 jan bodnar') 7 de 11 27/04/2008 1:04 .AboutDialogInfo() The first thing to do is to create a wx. File Hunter is distributed in the hope that it will be useful.SetVersion('1. MA 02111-1307 info = wx. info.AboutBox(info) app = wx. the text should info = wx. But in real world programs. -1.AboutDialogInfo object.SetName('File Hunter') info. if we want to translate our application to other languages.SetName('File Hunter') info. """ It is not the best idea to put too much text into the code of the application.com/wxpython/dialogs/ under the terms of the GNU General Public License as published by the Free Software Fou either version 2 of the License. 'About dialog box') app. or (at your option) any later version. It does not taky any parameters. For example.SetVersion('1. so I put be placed separately inside a file.png'. Inc. write to the Free Software Foundation.App() AboutDialogBox(None.BITMAP_TYPE_PNG)) info. The constructor is empty.AddArtist('The Tango crew') info. wx.zetcode. powerful batch renaming. It helps us with the maintenace of our application. all the text into the code. Boston.wxPython dialogs http://www.SetLicence(licence) info.SetIcon(wx.SetWebSite('http://www. but WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOS See the GNU General Public License for more details.BITMAP_TYPE_PNG)) info. advanced search capabilities.zetcode. extensive archive handling and more. Suite 330.AddTranslator('jan bodnar') wx. file comparison. Features include powerful built-in editor.Icon('icons/hunter.SetDescription(description) info. if not.png'.MainLoop() description = """File Hunter is an advanced file manager for the Unix operating system..0') info.Icon('icons/hunter. I don't want to make the example too complex.SetIcon(wx.com') info. 59 Temple Place. wx.0') info.AddDocWriter('jan bodnar') info.AddDeveloper('jan bodnar') info.SetCopyright('(C) 2007 jan bodnar') info.SetDescription(description) info. You should have received a copy of the GNU General Public License along with File Hunter.AboutDialogInfo() info. AboutBox(info) In the end we create a wx. we must implement our about dialog manually.AboutBox widget.zetcode.zetcode.wxPython dialogs http://www. About dialog box A custom dialog In the next example we create a custom dialog.AddDeveloper('jan bodnar') info. To provide this funcionality.SetWebSite('http://www.AddTranslator('jan bodnar') The next thing to do is to call all necessary methods upon the created wx.AddArtist('The Tango crew') info.AddDocWriter('jan bodnar') info. 8 de 11 27/04/2008 1:04 . An image editing application can change a color depth of a picture. we could create a suitable dialog.com/wxpython/dialogs/ info. And of course.AboutDialogInfo object.SetLicence(licence) info.AboutDialogInfo object. if we want to have an animation or some other eye candy. wx.com') info. The only parameter it takes is the wx. 30)) hbox. size=(70.Add(hbox.ShowModal() chgdep. 'Custom'. 'Ok'.ALIGN_CENTER | wx. (5. 5) vbox.BoxSizer(wx. wx.Dialog.TextCtrl(panel. 150)) wx.SetSizer(vbox) class ColorDepth(wx.wxPython dialogs http://www.zetcode. -1. id=ID_DEPTH) self. ''.CreateToolBar() toolbar.com/wxpython/dialogs/ #!/usr/bin/python # colordepth.Bind(wx. (95.py import wx ID_DEPTH = 1 class ChangeDepth(wx. (15. 80)) wx. id.Panel(self.LEFT.HORIZONTAL) okButton = wx.__init__(self. -1) vbox = wx.Button(self.VERTICAL) wx. 30).Frame. title.Add(closeButton. 105)) hbox = wx.OnChangeDepth. -1.Button(self. 30)) closeButton = wx. -1. size=(250.App() ColorDepth(None. size=(350. '2 Colors'. 'Close'. 10) self.EVT_TOOL. title. 1) hbox.Show(True) def OnChangeDepth(self. 55)) wx. parent.RB_GROUP) wx.AddLabelTool(ID_DEPTH. size=(70.Add(panel) vbox.TOP | wx. title): wx. (240.Destroy() app = wx. -1. 105)) wx. id.Add(okButton. 'Change Color Depth') chgdep. event): chgdep = ChangeDepth(None.MainLoop() class ChangeDepth(wx. 1.RadioButton(panel. -1.Dialog): 9 de 11 27/04/2008 1:04 . parent. parent.png')) self. title): wx. 220)) toolbar = self. 210)) panel = wx. '16 Colors'.BOTTOM. -1. -1. '') app. -1.RadioButton(panel.BoxSizer(wx. wx. (15.Bitmap('icons/color. (15. ''. parent. id.StaticBox(panel. '256 Colors'.RadioButton(panel. (15.Centre() self. self. style=wx. id. -1. 5). 'Colors'.__init__(self. wx. 1.RadioButton(panel. -1.Dialog): def __init__(self.Frame): def __init__(self. 210)) In our code example we create a custom ChangeDepth dialog. parent. title. size=(250. There is a clear difference in the titlebar of the windows. chgdep = ChangeDepth(None. difference between the dialog and the top level window.Dialog.__init__(self. title): wx. We must not forget to destroy our dialog.ShowModal() chgdep.wxPython dialogs http://www. Ask the wxExperts! Home ‡ Contents ‡ Top of Page 10 de 11 27/04/2008 1:04 . parent. id. Then we call the ShowModal() dialog.com/wxpython/dialogs/ def __init__(self.Dialog widget. 'Change Color Depth') chgdep. The dialog in Figure: A custom dialog Python Purse on sale TT-Solutions Genuine python handbags on sale We Custom make handbag for you wxWidgets (wxWindows) consulting and development. Notice the visual the following figure has been activated.zetcode. We inherit from a wx. id. We cannot work with the toplevel window until the dialog is destroyed. -1.Destroy() We instantiate a ChangeDepth class. wxPython dialogs http://www. 2007 © 2007 Jan Bodnar 11 de 11 27/04/2008 1:04 .com/wxpython/dialogs/ last modified June 5.zetcode. ComboBox wx.Button wx. Ruby. Contents Debugger. C++.BU_TOP wx. Python Core Widgets In this section.StaticText wx.BU_LEFT wx.ToggleButton wx. wx.ScrolledWindow wx.RadioButton wx. Services.wxPython widgets http://www.BU_EXACTFIT wx.CheckBox wx. It contains a text string.StaticLine wx.Button styles wx.Gauge wx.SplitterWindow wx. Browser. Java J2EE.BU_RIGHT wx.ListBox wx. It is used to trigger an action. Faster.Button wx.com/wxpython/widgets/ Python IDE HomeEasier Python Development Editor.StaticBox wx. wx.BitmapButton wx.SpinCtrl wx.StatusBar wx. we will introduce basic widgets in wxPython.Slider wx.zetcode. and more Scrum Formation.Panel wx. Conseil TDD.NO_BORDER 1 de 29 27/04/2008 1:04 .BU_BOTTOM wx.Button is a simple widget.Notebook wx. Each widget will have a small code example. Move((randx.EVT_BUTTON.com/wxpython/widgets/ Figure: Buttons.Bind(wx. 130).Dialog.ShowModal() self. size=(APP_SIZE_X. screensize.py import wx import random APP_SIZE_X = 300 APP_SIZE_Y = 200 class MyButtons(wx. id. (150. parent.APP_SIZE_X) randy = random. 130)) wx.wxPython widgets http://www.GetDisplaySize() randx = random.py #!/usr/bin/python # buttons. 'Random Move'. self.ToggleButton 2 de 29 27/04/2008 1:04 .Button(self. (50. 'buttons. event): self.EVT_BUTTON.y .APP_SIZE_Y) self. title): wx. title.Close(True) def OnRandomMove(self.zetcode.randrange(0. screensize.Button(self. -1.OnClose. 1. 'Close'.OnRandomMove. id=2) self. id.__init__(self. -1)) self.MainLoop() wx.x .App(0) MyButtons(None.py') app. parent.Centre() self. (110. APP_SIZE_Y)) wx.Bind(wx.Dialog): def __init__(self.Destroy() def OnClose(self. 2.randrange(0. event): screensize = wx. self. randy)) app = wx. id=1) self. (20.colour.Set(0. 'green'.colour. 0) wx.EVT_TOGGLEBUTTON.colour. There are situations where this functionality fits well.colour. id. size=(300.SUNKEN_BOR self.wxPython widgets http://www.Bind(wx. You toggle between these two states by clicking on it.ToggleBlue.Colour(0.Blue() if self.__init__(self.Bind(wx.ToggleButton(self.Dialog. self. (150. 'blue'.panel = wx. blue) else: self.EVT_TOGGLEBUTTON. (110. 'red'.py #!/usr/bin/python # togglebuttons. 1.ToggleGreen. parent.Centre() self. 60)) wx.py import wx class ToggleButtons(wx.SetBackgroundColour(self.panel. 20). 200)) self.Red(): self.colour.ToggleButton(self. title): wx. id=3) self.com/wxpython/widgets/ wx.ToggleRed. 2.SetBackgroundColour(self.colour) self.EVT_TOGGLEBUTTON.ToggleButton(self. self.Panel(self.colour) 3 de 29 27/04/2008 1:04 . id=2) self. parent. 110). 25)) wx. style=wx. title.ToggleButton is a button that has two states. (20. Pressed and not pressed.Dialog): def __init__(self. -1.Bind(wx.panel. self.colour = wx. id=1) self. blue) self. green. event): green = self.Set(255. 0. (20. Figure: Togglebuttons.Green() blue = self. 3. green.Destroy() def ToggleRed(self. id.zetcode. 100)) self.ShowModal() self. colour.py') app.colour. event): red = self.Set(red. where bitmap buttons are used.Red() green = self. -1.colour.Blue() if self.colour. We can set a specific bitmap for those states.App() ToggleButtons(None.colour) def ToggleBlue(self. Selected.Set(red.SetBackgroundColour(self. A video player is a nice example.com/wxpython/widgets/ def ToggleGreen(self.Blue(): self.Green() if self.panel. green.panel.colour.colour.SetBackgroundColour(self. 255) self.colour) app = wx.BitmapButton A bitmap button is a button. 0) else: self. blue) self.wxPython widgets http://www. 0. pause. We can So we create a skeleton of a video player in our next example. 'togglebuttons.colour.zetcode. previous and volume bitmap buttons there.Set(red.py 4 de 29 27/04/2008 1:04 .colour.colour. that displays a bitmap.Green(): self. event): red = self.colour. blue) else: self. A bitmap button can have three other states. Figure: Player. green.MainLoop() wx.Red() blue = self. next. 255. see play. focused and displayed.Set(red. EXPAND | wx.BoxSizer(wx.Add(prev) hbox2. '&Tools') menubar. 1000) pause = wx. 0.Append(tools.SetBackgroundColour(wx.BLACK) pnl2 = wx.RIGHT.Panel(self. border=5) hbox2.Bitmap('icons/stock_media-pause. -1.com/wxpython/widgets/ #!/usr/bin/python # player. wx.Add((-1.BOTTOM.zetcode.VERTICAL) hbox1 = wx.Add(hbox1.HORIZONTAL) hbox1.Append(file. size=(350. flag=wx.BoxSizer(wx. 1) hbox2.Add(slider2.Add(play.Append(view. -1) pnl1 = wx. border=10) vbox. -1)) vbox = wx.Append(help.Append(play.Add(hbox2.Add(next.png')) play = wx.SetMenuBar(menubar) slider1 = wx. -1.Append(101.BoxSizer(wx. flag=wx.Bitmap('icons/stock_media-next.Slider(pnl2.Menu() play = wx.wxPython widgets http://www.Add(volume) hbox2. 0. 0. border=5) hbox2. border=5) vbox. wx. '&Help') self.BitmapButton(pnl2. wx.Slider(pnl2. 0. -1) pnl1.Bitmap('icons/stock_media-play. parent.TOP | wx.png')) volume = wx. '&Play') menubar.py import wx class Player(wx. 300)) panel = wx.HORIZONTAL) hbox2 = wx. title.Add(slider1.Menu() file.Menu() view = wx. id. id. wx. wx.BitmapButton(pnl2. 1. title): wx. -1.BitmapButton(pnl2.png')) prev = wx.Bitmap('icons/volume.Frame.BitmapButton(pnl2. wx. -1.Frame): def __init__(self. -1. -1 ) menubar = wx. 'F&avorites') menubar. size=(120. '&File') menubar.BitmapButton(pnl2.MenuBar() file = wx. flag=wx.EXPAND) pnl2.SetSizer(vbox) 5 de 29 27/04/2008 1:04 . 100.__init__(self.Add(pause) hbox2.Panel(self.png')) next = wx.Panel(self. flag=wx. -1. 'Quit application') menubar.Menu() favorites = wx. parent.Menu() help = wx.LEFT.Append(favorites.Menu() tools = wx.Bitmap('icons/stock_media-prev. -1. -1). '&quit'. 1) hbox2. '&View') menubar.LEFT.png')) slider2 = wx. 1) hbox2.Add(volume) Here we put some space between the previous button and the space will grow. It can be horizontal or vertical. 300)) Here we set the minimum size of the player. border=10) self.wxPython widgets http://www.EXPAND) sizer.zetcode.Add(pnl1.StaticLine styles wx.CreateStatusBar() self.Add(pnl2.SetMinSize((350.TOP. that the self.BoxSizer(wx.BitmapButton is self explanatory.py script displays central look more visually attractive. 1. hbox2.StaticLine This widget displays a simple line on the window. wx.LI_HORIZONTAL wx. flag=wx.png')) The creation of the wx. The wx. wx. when we resize the window.Centre() self.SetMinSize((350.EXPAND | wx. -1.BitmapButton(pnl2.com/wxpython/widgets/ sizer = wx. -1).StatLine makes it 6 de 29 27/04/2008 1:04 . The proportion is set to 1.VERTICAL) sizer.BOTTOM | wx. centraleurope.Add(prev) hbox2.Add((-1. -1.SetSizer(sizer) self.Bitmap('icons/stock_media-pause. It does not make much sense to shrink the window below some value.LI_VERTICAL european countries and their population. 300)) self. This means. volume button. wx.App() Player(None. 'Player') app.Show() app = wx. flag=wx.MainLoop() pause = wx. wx. title): wx.StaticText(self. -1.Font(10. -1.Dialog. 140)) 'Germany'.wxPython widgets http://www.zetcode.py #!/usr/bin/python # centraleurope. (25. size=(360. -1. 120)) 'Czech Republic'. (25. wx. (25. 100)) '38 635 000'. 140)) '82 443 000'. 370)) font = wx. -1.py import wx class CentralEurope(wx.StaticLine(self. -1. -1. 160)) '2 001 000'. wx. -1. -1. 'Slovakia'.StaticText(self. (250. wx.1)) wx. -1. -1.com/wxpython/widgets/ Figure: CentralEurope. -1. ID. 180)) 'Austria'. (130. -1.DEFAULT.StaticText(self.StaticText(self. wx.StaticText(self.__init__(self. -1.StaticText(self. 200)) 'Switzerland'. wx. -1. (250. 100)) 'Poland'. 15)) heading.BOLD) heading = wx. 160)) 'Slovenia'.StaticText(self.StaticText(self. 120)) '10 240 000'. wx.StaticText(self. wx. 220)) '5 379 000'. -1. (25. parent. parent. (300. 80)) 'Hungary'.StaticText(self. wx. (250. (25. (25.SetFont(font) wx.StaticText(self. wx.StaticText(self. 50). -1. wx. 80)) '10 084 000'. (25. title.NORMAL. 180)) 7 de 29 27/04/2008 1:04 . (250. wx.Dialog): def __init__ (self. (250.StaticText(self.StaticText(self. wx. wx. wx. (250. 'The Central Europe'. (25. (25.StaticText(self. wx. ID. (240.GetFont() sum_font.Button(self. -1.MainLoop() wx.SetFont(sum_font) wx. id=1) self.StaticLine(self.Bind(wx. '8 032 000'.py') app. -1. 1. 200)) wx.StaticText(self.SetWeight(wx.1)) sum = wx. self.StaticText A wx. (140.BOLD) sum. (300. (25.py 8 de 29 27/04/2008 1:04 .ShowModal() self.com/wxpython/widgets/ wx. 260). 30)) self.Destroy() def OnOk(self.wxPython widgets http://www.Close() app = wx. 280)) sum_font = sum.ALIGN_CENTER / wx. -1. event): self. (60. '164 102 000'.Centre() self.StaticText widget displays one or more lines of read-only text.EVT_BUTTON.App() CentralEurope(None. (250.ST_NO_AUTORESIZE Figure: statictext. 'centraleurope. '7 288 000'.ALIGN_RIGHT iwx.ALIGN_LEFT wx. 220)) wx. -1.StaticText Styles wx. -1. (250.ALIGN_CENTRE wx.StaticText(self.OnOk.StaticText(self. 'Ok'. 310).zetcode. wx. lyrics1.MainLoop() wx. parent. title): wx. It is used to logically group various widgets. parent. wx. id.wxPython widgets http://www.com/wxpython/widgets/ #!/usr/bin/python # statictext.Add(st2.ALIGN_CENTRE) st2 = wx. of the static box. 1.zetcode.ALIGN_CENTRE) vbox. title) lyrics1 = '''I'm giving up the ghost of love in the shadows cast on devotion She is the one that I adore creed of my silent suffocation Break this bittersweet spell on me lost in the arms of destiny''' lyrics2 = '''There is something in the way You're always somewhere else Feelings have deserted me To a point of no return I don't believe in God But I pray for you''' vbox = wx.StaticText(panel. -1. lyrics2.Frame.EXPAND | wx.BOTTOM. 15) vbox.BOTTOM. 1.Centre() self. -1) st1 = wx.EXPAND | wx.TOP | wx.py') app. -1.Panel(self.__init__(self.SetSizer(vbox) self.VERTICAL) panel = wx. style=wx. and that those widgets should be siblings. id.App() StaticText(None.Show(True) app = wx.TOP | wx. wx. widgets that it contains. 9 de 29 27/04/2008 1:04 .py import wx class StaticText(wx.Add(st1.BoxSizer(wx. -1. 15) panel.StaticText(panel.Frame): def __init__(self. Note that this widget must be created before the not children. style=wx.StaticBox This is a kind of a decorator widget. 'statixtext. (5. 95)) wx. event): self.py #!/usr/bin/python # staticbox. title. User can select only one option from the supplied string list.Button(self. 55)) wx. id. (15. -1. 230)) wx.zetcode. self. a button with a down arrow image and a listbox.ShowModal() self.Centre() self. parent.ComboBox has the following constructor: 10 de 29 27/04/2008 1:04 . When you press the button.OnClose.StaticBox(self.Bind(wx.CheckBox(self. wx. 'staticbox.wxPython widgets http://www. 185). 5). 'Ok'.Dialog): def __init__(self.MainLoop() wx. -1.Close() app = wx. title): wx. -1.App() StaticBox(None.py import wx class StaticBox(wx. (60.ComboBox is a combination of a single line text field. (15.py') app. -1). 30)) wx.Dialog. (90. -1. (55. parent.SpinCtrl(self. min=1. -1 . max=120) wx. 170)) wx.Destroy() def OnClose(self. -1)) self. (15. 'Personal Info'. 90). size=(250.'Male'. id=1) self. '1'.CheckBox(self. id. 1.__init__(self. size=(240.StaticText(self.EVT_BUTTON.ComboBox wx.'Married'. (60.com/wxpython/widgets/ Figure: staticbox. -1 . a listbox appears. 'Age'. jpg'.ComboBox(int id. 'Tom Wolfe'.DefaultPosition. 'balzac.jpg'] authors = ['Leo Tolstoy'. 'wolfe. style=wx.picture = wx. pos=(50.py import wx class ComboBox(wx.images = ['tolstoy.py #!/usr/bin/python # combobox. 'zweig. 'Close'.Button(self. -1.Validator validator=wx.DefaultValid string name=wx. 'Lion Feuchtwanger'.StaticBitmap(panel) panel. string value=''. title.ComboBoxNameStr) wx.jpg'. (75. int style=0.__init__(self. 'pasternak. id. 270)) panel = wx. 127).CB_DROPDOWN wx. 'John Galsworthy'. -1. id.wxPython widgets http://www. 'Boris Pasternak'. title): wx.ComboBox styles wx.CB_READONLY) wx. 'Stefan Zweig'] wx.SUNKEN_BORDER) self.Panel(self. size=(250.Dialog): def __init__(self. 'feuchtwanger.List choices=wx.jpg'.jpg'. (100.SetBackgroundColour(wx. 'Honore de Balzac'.Size size=w wx.jpg'. (80. size=(150.com/wxpython/widgets/ wx. 170). 20). 220)) 11 de 29 27/04/2008 1:04 .ComboBox(self. wx. 1.EmptyList.Dialog. -1). style=wx.zetcode.Point pos=wx. parent. parent.CB_SORT Figure: combobox.CB_READONLY wx. wx. choices=authors. wx. 'galsworthy.WHITE) self. GetSelection() self.Bind(wx. id. event): item = event.OnClose.CheckBox is a widget that has two states.ShowModal() self. It is a box with a label. parent.SetFocus() self.__init__(self. id=1) self.MainLoop() wx.py') app. it is represented by a tick in a Figure: checkbox.SetBitmap(wx.App() ComboBox(None. -1.images[item])) app = wx. wx. title): wx. self.EVT_COMBOBOX.OnSelect) self. The label can be set to the right or to the left of box. On and Off.picture.Centre() self.zetcode.Frame): def __init__(self. event): self.CheckBox wx. parent. 170)) panel = wx.EVT_BUTTON. size=(250.Close() def OnSelect(self.Frame.py #!/usr/bin/python # checkbox.picture.com/wxpython/widgets/ self. id. self.py import wx class CheckBox(wx.Panel(self.CheckBox Styles wx.Destroy() def OnClose(self. -1) 12 de 29 27/04/2008 1:04 . 'combobox.Bitmap('images/' + self. If the checkbox is checked. title.ALIGN_RIGHT the box.wxPython widgets http://www.Bind(wx. StatusBar As it's name indicates.StatusBar for us. We can manually we can simply call the CreateStatusBar() method.SetValue(True) wx.EVT_CHECKBOX(self.Frame widget and five other widgets. If we hover a mouse pointer over a widget.cb = wx. 10)) self.wxPython widgets http://www.StatusBar. -1.App() CheckBox(None.py #!/usr/bin/python # statusbar. event): if self.Show() self. It can be used as an alternative to dialogs.GetValue(): self. In our example. self.SetTitle('') app = wx.StatusBar and call SetStatusBar() method or method creates a default wx.StatusBar Figure: statusbar. -1.zetcode.Centre() def ShowTitle(self.SetTitle('checkbox.GetId().MainLoop() wx.cb. it's description is shown on the wx.py') else: self. We can create a wx. the wx.cb.py 13 de 29 27/04/2008 1:04 . 'Show Title'.py') app.StatusBar widget is used to display application status information. self. It can be divided into several parts to show different kind of information.StatusBar in two ways.com/wxpython/widgets/ self. create our own wx.CheckBox(panel.ShowTitle) self. (10. 'checkbox. The latter since dialogs are ofted abused and they are disliked by most users. we have a wx. We can insert other widgets into the wx.cb. 'Button'. event): self.SetStatusText('Button widget') event. id=1) button.Slider(panel. event): self.SetMinSize((250. 5.EnterText. ''. self. title.zetcode.sb.sb. 3. parent. -1.Bind(wx.Bind(wx.SetStatusText('ComboBox widget') event. (120. 4. 'CheckBox'. 200). (120.Frame.Skip() app = wx.CLOSE_BOX) panel = wx.EVT_ENTER_WINDOW.Skip() def EnterPanel(self.Skip() def EnterSlider(self.SYSTEM_MENU | wx.Bind(wx.EnterCombo. All other RadioButtons defined after the first RadioButton with this style flag is set will be added to the function 14 de 29 27/04/2008 1:04 . 200)) self.com/wxpython/widgets/ import wx class Statusbar(wx. 22)) slider = wx.SetStatusText('Panel widget') event. 1) button = wx.Panel(self. event): self.sb.CAPTION | wx. (20.RadioButton wx.SetStatusText('Slider widget') event. event): self.EVT_ENTER_WINDOW. self.ComboBox(panel. 20)) text = wx.EnterPanel. A group of radio buttons is defined by having the first RadioButton in the group contain the wx.CreateStatusBar() self.MainLoop() wx. style=wx.Centre() def EnterButton(self. self. size=(250.EnterButton.Show(True) self. 90)) combo = wx.SetMaxSize((250. (20. id=4) slider.sb = self. self.__init__(self.sb. id=5) self.EnterSlider.sb.Button(panel. title): wx.EVT_ENTER_WINDOW. 1. -1)) panel.EVT_ENTER_WINDOW.Skip() def EnterCombo(self.py') app. self. 90). id. 200)) self. 2.Bind(wx.SetStatusText('CheckBox widget') event.RadioButton is a widget that allows the user to select a single exclusive choice from a group of options. (110.RB_GROUP style. id. 6.CheckBox(panel.App() Statusbar(None. 10. event): self. id=3) combo. 'statusbar.EVT_ENTER_WINDOW. parent.Bind(wx.Skip() def EnterText(self. id=2) text.Frame): def __init__(self.wxPython widgets http://www. EVT_RADIOBUTTON. size=(210.CB_SORT wx. (10. 'Value C'.Frame): def __init__(self.RB_SINGLE Figure: radiobutton.rb1 = wx. self. 30)) self. self. 2) app = wx. 150)): wx. style=wx.rb1. -1. 1) self.zetcode.Panel(self.RadioButton Styles wx.SetStatusText(state2.rb3 = wx.__init__(self.py #!/usr/bin/python # radiobuttons. id=self.GetId()) self. -1) self. 10).SetVal.CreateStatusBar(3) self. wx. parent.statusbar.GetId()) self. id=self.Centre() self.statusbar.EVT_RADIOBUTTON.GetValue()) self.RadioButton(panel.RB_GROUP wx. 'Value B'.Show(True) def SetVal(self. parent.py import wx class RadioButtons(wx.Bind(wx. 0) self.SetVal.App() 15 de 29 27/04/2008 1:04 .RadioButton(panel.GetValue()) state2 = str(self.SetVal(True) self. id=self.RB_GROUP self.rb3. title) panel = wx. -1.EVT_RADIOBUTTON.GetValue()) state3 = str(self. self. -1.SetVal.com/wxpython/widgets/ group of the first RadioButton. id.GetId()) self. event): state1 = str(self.rb1.rb2. (10. id.rb2 = wx.Bind(wx.rb2. (10.Frame. title.rb3.Bind(wx.SetStatusText(state3.RB_GROUP flag will start a new radio button group. 'Value A'.statusbar. 50)) self.statusbar = self.wxPython widgets http://www.RadioButton(panel.SetStatusText(state1. Declaring another RadioButton with the wx. wxPython widgets RadioButtons(None, -1, 'radiobuttons.py') app.MainLoop() http://www.zetcode.com/wxpython/widgets/ wx.Gauge wx.Gauge is a widget that is used, when we process lengthy tasks. wx.Gauge styles wx.GA_VERTICAL wx.GA_HORIZONTAL Figure: gauge.py # gauge.py import wx class Gauge(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title, size=(300, 200)) self.timer = wx.Timer(self, 1) self.count = 0 self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) panel = wx.Panel(self, -1) vbox = wx.BoxSizer(wx.VERTICAL) hbox1 = wx.BoxSizer(wx.HORIZONTAL) hbox2 = wx.BoxSizer(wx.HORIZONTAL) hbox3 = wx.BoxSizer(wx.HORIZONTAL) self.gauge = wx.Gauge(panel, -1, 50, size=(250, 25)) self.btn1 = wx.Button(panel, wx.ID_OK) self.btn2 = wx.Button(panel, wx.ID_STOP) self.text = wx.StaticText(panel, -1, 'Task to be done') self.Bind(wx.EVT_BUTTON, self.OnOk, self.btn1) self.Bind(wx.EVT_BUTTON, self.OnStop, self.btn2) 16 de 29 27/04/2008 1:04 wxPython widgets http://www.zetcode.com/wxpython/widgets/ hbox1.Add(self.gauge, 1, wx.ALIGN_CENTRE) hbox2.Add(self.btn1, 1, wx.RIGHT, 10) hbox2.Add(self.btn2, 1) hbox3.Add(self.text, 1) vbox.Add((0, 30), 0) vbox.Add(hbox1, 0, wx.ALIGN_CENTRE) vbox.Add((0, 20), 0) vbox.Add(hbox2, 1, wx.ALIGN_CENTRE) vbox.Add(hbox3, 1, wx.ALIGN_CENTRE) panel.SetSizer(vbox) self.Centre() self.Show(True) def OnOk(self, event): if self.count >= 50: return self.timer.Start(100) self.text.SetLabel('Task in Progress') def OnStop(self, event): if self.count == 0 or self.count >= 50 or not self.timer.IsRunning(): return self.timer.Stop() self.text.SetLabel('Task Interrupted') wx.Bell() def OnTimer(self, event): self.count = self.count +1 self.gauge.SetValue(self.count) if self.count == 50: self.timer.Stop() self.text.SetLabel('Task Completed') app = wx.App() Gauge(None, -1, 'gauge.py') app.MainLoop() wx.Slider wx.Slider is a widget that has a simple handle. This handle can be pulled back and forth. This way we are choosing a value for a specific task. Say we want to input into our application the age of a customer. For this purpose, wx.Slider might be a good choice. wx.Slider styles wxSL_HORIZONTAL wxSL_VERTICAL wxSL_LABELS wxSL_LEFT wxSL_TOP wxSL_RIGHT wxSL_BOTTOM wxSL_AUTOTICKS wxSL_INVERSE 17 de 29 27/04/2008 1:04 wxPython widgets http://www.zetcode.com/wxpython/widgets/ Figure: slider.py #!/usr/bin/python # slider.py import wx class Slider(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title, size=(300, 150)) panel = wx.Panel(self, -1) vbox = wx.BoxSizer(wx.VERTICAL) hbox = wx.BoxSizer(wx.HORIZONTAL) self.sld = wx.Slider(panel, -1, 200, 150, 500, (-1, -1), (250, -1), wx.SL_AUTOTICKS | wx.SL_HORIZONTAL | wx.SL_LABELS) btn1 = wx.Button(panel, 1, 'Adjust') btn2 = wx.Button(panel, 2, 'Close') wx.EVT_BUTTON(self, 1, self.OnOk) wx.EVT_BUTTON(self, 2, self.OnClose) vbox.Add(self.sld, 1, wx.ALIGN_CENTRE) hbox.Add(btn1, 1, wx.RIGHT, 10) hbox.Add(btn2, 1) vbox.Add(hbox, 0, wx.ALIGN_CENTRE | wx.ALL, 20) panel.SetSizer(vbox) self.Centre() self.Show(True) def OnOk(self, event): val = self.sld.GetValue() self.SetSize((val*2, val)) def OnClose(self, event): self.Close() app = wx.App() Slider(None, -1, 'slider.py') app.MainLoop() wx.ListBox 18 de 29 27/04/2008 1:04 wxPython widgets http://www.zetcode.com/wxpython/widgets/ wx.Listbox is a widget that consists of a scrolling box and a list of on whether it is created as a single or multiple selection box. Selected items are marked. items. User can select one or more items from that list. It depends listbox.py example consists of four different widgets. wx.Listbox, with sizer-s. wx.Listbox has a list of six different world times. These abbreviations are explained in the second wx.TextCtrl. widget is used to update the time every 100 miliseconds. wx.TextCtrl, wx.StaticText and wx.Button. Widgets are organized Current time is displayed in the wx.StaticText widget. wx.Timer Figure: listbox.py #!/usr/bin/python # listbox.py import wx from time import * class Listbox(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title, size=(550, 350)) zone_list = ['CET', 'GMT', 'MSK', 'EST', 'PST', 'EDT'] self.full_list = { 'CET': 'Central European Time', 'GMT': 'Greenwich Mean Time', 'MSK': 'Moscow Time', 'EST': 'Eastern Standard Time', 'PST': 'Pacific Standard Time', 'EDT': 'Eastern Daylight Time' 19 de 29 27/04/2008 1:04 wxPython widgets } self.time_diff = { 'CET' : 1, 'GMT' : 0, 'MSK': 3, 'EST': -5, 'PST': -8, 'EDT': -4 } vbox = wx.BoxSizer(wx.VERTICAL) hbox1 = wx.BoxSizer(wx.HORIZONTAL) hbox2 = wx.BoxSizer(wx.HORIZONTAL) hbox3 = wx.BoxSizer(wx.HORIZONTAL) self.timer = wx.Timer(self, 1) self.diff = 0 panel = wx.Panel(self, -1) http://www.zetcode.com/wxpython/widgets/ self.time_zones = wx.ListBox(panel, 26, (-1, -1), (170, 130), zone_list, wx.LB_SINGLE) self.time_zones.SetSelection(0) self.text = wx.TextCtrl(panel, -1, 'Central European Time', size=(200, 130), style=wx.TE_MULTILINE) self.time = wx.StaticText(panel, -1, '') btn = wx.Button(panel, wx.ID_CLOSE, 'Close') hbox1.Add(self.time_zones, 0, wx.TOP, 40) hbox1.Add(self.text, 1, wx.LEFT | wx.TOP, 40) hbox2.Add(self.time, 1, wx.ALIGN_CENTRE) hbox3.Add(btn, 0, wx.ALIGN_CENTRE) vbox.Add(hbox1, 0, wx.ALIGN_CENTRE) vbox.Add(hbox2, 1, wx.ALIGN_CENTRE) vbox.Add(hbox3, 1, wx.ALIGN_CENTRE) panel.SetSizer(vbox) self.timer.Start(100) wx.EVT_BUTTON(self, wx.ID_CLOSE, self.OnClose) wx.EVT_LISTBOX(self, 26, self.OnSelect) wx.EVT_TIMER(self, 1, self.OnTimer) self.Show(True) self.Centre() def OnClose(self, event): self.Close() def OnSelect(self, event): index = event.GetSelection() time_zone = self.time_zones.GetString(index) self.diff = self.time_diff[time_zone] self.text.SetValue(self.full_list[time_zone]) def OnTimer(self, event): ct = gmtime() print_time = (ct[0], ct[1], ct[2], ct[3]+self.diff, ct[4], ct[5], ct[6], ct[7], -1) 20 de 29 27/04/2008 1:04 So I made a wxPython example as well. title): wx. 310)) 21 de 29 27/04/2008 1:04 .SetLabel(strftime("%H:%M:%S". print_time)) app = wx.py #!/usr/bin/python # spinctrl.SpinCtrl This widget lets you increment and decrement a value.App() Listbox(None.__init__(self. title. wx. User can enter a value into a box or increment/decrement it by these two arrows. id.SpinCtrl wx. size=(350.SP_WRAP Figure: converter.com/wxpython/widgets/ self.MainLoop() wx.SP_ARROW_KEYS wx.wxPython widgets http://www.time. id. parent.py import wx class Converter(wx. 'listbox. It has two up and down arrow buttons for this purpose.Dialog. This primer books. parent.Dialog): def __init__(self. -1.py') app. example is very popular and can be found in most programming styles Converter script converts Fahrenheit temperature to Celsius.zetcode. SetRange(-459. The user can dynamically resize those parts with the mouse pointer. 22 de 29 27/04/2008 1:04 .SpinCtrl(self. -1. (185. 'Compute'.sc.StaticText(self.StaticText(self.StaticText(self. self.EVT_CLOSE(self. -1.SetFocus() clear_btn = wx. -1. -1.OnClose) self.sc = wx. 1. 250)) wx.OnClose) wx.EVT_BUTTON(self.EVT_BUTTON(self.Destroy() app = wx. 80)) wx.OnCompute) wx. (20.celsius.com/wxpython/widgets/ wx. 'Celsius: '. (20.0.ShowModal() self. ''. (150.20 wx. 150)) self. 2) self. 1000) self. -1)) self. Such a solution can be seen in mail clients (evolution) or in burning software (k3b). (70. ''.SetValue(0) compute_btn = wx. 2. self.App() Converter(None.wxPython widgets http://www.zetcode. 1.SplitterWindow This widget enables to split the main area of an application into parts. (60. (20.celsius = wx. -1. 'Converter') app.sc. 'Fahrenheit: '.GetValue() cels = round((fahr-32)*5/9. self. 2. -1.MainLoop() wx.Destroy() def OnCompute(self. 250)) compute_btn.Button(self.SetLabel(str(cels)) def OnClose(self.Button(self.StaticText(self. event): fahr = self. 'Close'.Centre() self. 150)) self. event): self. (150. 'Convert Fahrenheit temperature to Celsius'. You can split an area vertically or horizontally. 75).sc. StaticText(panel1.py import wx class Splitterwindow(wx. -1. id.py') app. size=(350. 100). we When the window is smaller than our image.LIGHT_GREY) panel2 = wx.Panel(splitter.ALIGN_CENTRE) panel1. (100.__init__(self. or that you can't.SetBackgroundColour(wx. In our example.SetBackgroundColour(wx.Frame.py #!/usr/bin/python # splitterwindow.MainLoop() wx. title): wx. -1) panel2.ScrolledWindow This is one of the container widgets. style=wx.Centre() self.Panel(splitter.SplitVertically(panel1. you are usually right''' splitter = wx. -1) wx.com/wxpython/widgets/ Figure: splitterwindow. Scrollbars are demonstrate such a case. when we have a larger area than a window can display. 300)) quote = '''Whether you think that you can. 'splitterwindow.wxPython widgets http://www. 23 de 29 27/04/2008 1:04 .Frame): def __init__(self. panel2) self.App() Splitterwindow(None.WHITE) splitter. id.SplitterWindow(self. -1) panel1 = wx.Show(True) app = wx. We place a large image into our window.zetcode. parent. quote. -1. It can be useful. parent. title. Frame): def __init__(self.Image('images/aliens.Show() app = wx.py #!/usr/bin/python # scrolledwindow.wxPython widgets displayed automatically.StaticBitmap(sw.10) self.SetScrollbars(20. 400)) sw = wx. title): wx. parent. -1.wx.zetcode.Scroll(50.App() ScrolledWindow(None.BITMAP_TYPE_JPEG).com/wxpython/widgets/ Figure: scrolledwindow. size=(500. 40) sw. 'Aliens') app.MainLoop() 24 de 29 27/04/2008 1:04 .ScrolledWindow(self) bmp = wx. title.ConvertToBitmap() wx.__init__(self. bmp) sw.py import wx class ScrolledWindow(wx. id. 20. -1. http://www.Centre() self. id.Frame.jpg'. parent. 55. Figure: notebook.NB_TOP wx.lib.sheet as sheet 25 de 29 27/04/2008 1:04 .NB_TOP.NB_LEFT wx. scrollbars.NB_RIGHT wx.py import wx import wx. You can position the Notebook widget using the following style flags: wx.zetcode.wxPython widgets http://www.com/wxpython/widgets/ The SetScrollbars() method creates horizontal and vertical scroll to the given position. By calling the Scroll() method we programmatically wx.Notebook widget joins multiple windows with corresponding tabs.NB_BOTTOM The default position is wx.Notebook wx.py #!/usr/bin/python # notebook. We add various widgets into the notebook wx. event): self.sheet3 = MySheet(nb) nb.CSheet): def __init__(self. style=wx. 'Sheet1') nb.Frame widget first. 'notebook. 'Quit'. It adds some basic functionality to the wx.SetNumberCols(50) class Notebook(wx. We put simple spreadsheet widgets.Close() app = wx. 101. parent. self.OnQuit) nb = wx.NB_BOTTOM style.Frame.StatusBar() self. -1.MenuBar() file = wx.MainLoop() In our example we create a notebook widget with wx.AddPage(self.AddPage(self.zetcode. the frame accordingly.SetFocus() self. size=(600. parent.Centre() self.sheet3.Panel wx.sheet2 = MySheet(nb) self.__init__(self. 500)) menubar = wx.statusbar = self.App() Notebook(None.py') app.Panel is a basic parent widget.sheet2.sheet1 = MySheet(nb) self.sheet1.wxPython widgets http://www.SetMenuBar(menubar) wx. title.AddPage(self.Append(file.__init__(self.Append(101.Window widget. title): wx. Then we place a 26 de 29 27/04/2008 1:04 .com/wxpython/widgets/ class MySheet(sheet.Frame): def __init__(self. parent): sheet.Menu() file.Show() def StatusBar(self): self. '&File') self.sheet module.CSheet.Notebook(self. It is therefore positioned on the bottom of widget with the AddPage() method. '' ) menubar. 'Sheet2') nb. id. id.CreateStatusBar() def OnQuit(self. -1.EVT_MENU(self. 'Sheet3') self. A Spreadsheet widget can be foung in wx.lib.SetNumberRows(50) self.NB_BOTTOM) self. Normally we create a wx. which is usually not used directly.sheet1. parent) self. Then we place widgets on the panel.zetcode.Panel(panel1. (5.wxPython widgets http://www.Frame): def __init__(self.BoxSizer(wx.VERTICAL) 27 de 29 27/04/2008 1:04 . Figure: panels.Add(panel12.Panel widgets.BoxSizer(wx. title) hbox = wx. style=wx.SetForegroundColour('WHITE') panel12 = wx.SetBackgroundColour('WHITE') vbox1. we can also combine panels to create interesting interface. -1. parent. However. -1) panel11 = wx. We use altogether six different wx.Panel(splitter.EXPAND) vbox1. wx.HORIZONTAL) splitter = wx.VERTICAL) panel1 = wx. 1. 'Feeds'. size=(-1.Panel(panel1.py #!/usr/bin/python # panels.__init__(self. -1) vbox1 = wx. 40)) panel11. In the following example we create a two side window with headers.Frame. wx. id.Panel widget inside this frame. -1.com/wxpython/widgets/ wx. parent.BORDER_SUNKEN) panel12.SplitterWindow(self. 0.SetSizer(vbox1) vbox2 = wx.StaticText(panel11.EXPAND) panel1. -1. title): wx. id. 5)) st1.py import wx class Panels(wx.BoxSizer(wx. This is the common scenario.SetBackgroundColour('#53728c') st1 = wx.Add(panel11. wx. vbox1. wx. id=1) hbox.EXPAND) Here we create the header panel.MainLoop() hbox = wx.Centre() self.SetSizer(hbox) self.CreateToolBar() toolbar.EXPAND) vbox2. wx. (5. -1) The wx. 0.BOTTOM. One will create a header and the other one will take up the rest of the parent panel.Add(panel22.Add(panel11.BORDER_RAISED) panel22. -1. -1.App() Panels(None.Panel(panel2.Close() app = wx.StaticText(panel11.HORIZONTAL) splitter = wx.Panel(panel2.Panel(panel1.SetBackgroundColour('#53728c') panel22 = wx. wx. event): self.SetSizer(vbox2) toolbar = self. panel11 = wx.StaticText(panel21.Add(splitter.Bitmap('icons/stock_exit.Realize() self. 'Panels') app. 'Exit'.EXPAND | wx. One panel will be placed on the left and one on the right side.AddLabelTool(1.EVT_TOOL.SetBackgroundColour('WHITE') vbox2.Bind(wx..Panel(splitter.Show(True) def ExitApp(self.png')) toolbar.SetBackgroundColour('#53728c') st1 = wx. style=wx. 1. size=(-1.zetcode. wx. 0.TOP | wx.ExitApp. panel2) self. Together we will use six panels. The 28 de 29 27/04/2008 1:04 . The header height is 40px. Each one will have other two panels. style=wx..BoxSizer(wx. -1.NO_BORDER) st2 = wx. 5)) st2.SplitterWindow will split our window into two parts.EXPAND) panel2. -1. 'Articles'. (5. -1.wxPython widgets http://www.SetForegroundColour('WHITE') panel21. 'Feeds'. self.SetForegroundColour('WHITE') .CreateStatusBar() splitter.com/wxpython/widgets/ panel2 = wx. 40)) panel11. 40). 5)) st1. size=(-1. -1.SplitterWindow(self.Add(panel21. -1) panel21 = wx. 5) self. 1.SplitVertically(panel1. BORDER_SUNKEN style. 1.zetcode. 2007 © 2007 Jan Bodnar 29 de 29 27/04/2008 1:04 . style=wx.wxPython widgets http://www. We make it expandable and set the proportion Ruby on Rails Development for business critical solutions backed by a fully managed service TT-Solutions wxWidgets (wxWindows) consulting and development. color is set to white. Ask the wxExperts! Home ‡ Contents ‡ Top of Page ZetCode last modified June 13.EXPAND) The bottom panel is created with wx. vbox1. The parameter to 1. wx. we make the panel12 = wx.BORDER_SUNKEN) panel12. The color of the static text is set to white. -1.Panel(panel1. (#53728c) We put a wx.com/wxpython/widgets/ color is set to dark blue. The position is 5px from left and 5px from top so that we have some space between the panel and the static text.. panel11 expandable and set the proportion to 0..StaticText inside the header panel.Add(panel12. In the end.SetBackgroundColour('WHITE') . In contrast. A wx. Not to mention the speed penalty. a list widget or an editor with advanced styling capabilities. All this widgets are created in C++. Such a languages like Python. intensive applications. In a single selection state or a multiple selection state. The wx.com/wxpython/advanced/ Home Contents Faster. They are simple to use. According to the The elements are numbered from zero. Quite enough. wxWidgets a C++ based toolkit. if we develop resource no competition to C++. 1 de 21 27/04/2008 1:05 . wxPython is a layer over widgets. New widgets and features emerge with every major released just two days ago. and more Python IDE eXtreme Programming Assistance Technique Java/J2ee. Debugger.ListBox widget is used for displaying and working with a list of items.0 has been A W X. high quality multimedia applications.Net/C#. documentation.ListBox. wxPython and wxWidgets are being developed all the time.ListBox is limited on GTK platform. A big advantage of wxPython over a competing PyGTK is the availability of a huge It does not provide new widgets. an html window. Easier Python Development Editor.zetcode.EVT_COMMAND_LISTBOX_SELECTED a larger project or names of our friends. we have to create it ourselves. in house developing or for studying computer will change rapidly over a short period of time. widget is quite complicated. The is generated when we double click an item in a wx. PERL or Ruby are not suitable for such tasks. it is a rectangle that has a list of strings inside.ListBox. Python. For example a tree widget. On the other hand. This event is generated when we select a string in a wx. module names of different states. a grid widget. a listbox widget. L I ST BOX W I D GET A wx. wxPython is a glue that amount of advanced widgets. We could use it for displaying a list of mp3 files. Dynamic Dynamic languages are great in various areas. release. If we need a quick solution or we need an application. PyGTK is a layer over a C based GKT+ toolkit. dynamic languages are programming. The number of second one is the wx.3. If we want to have a grid widget in our application using PyGTK.8. Ruby Advanced widgets in wxPython In the following chapters we will talk about advanced widgets. wxWidgets consists of a large group of combines python language with this toolkit. there is wxPython has several well known advanced widgets. games. book names.ListBox can be created in two single selection state is the default state. (22-Mar-2007). As it's name indicates. I think. There are two significant events in event.ListBox. It elements inside a wx. that superior to compiled languages. The first one is the wx. it is currently around 2000 elements. . They are great for prototyping.EVT_COMMAND_LISTBOX_DOUBLE_CLICKED event.Advanced widgets http://www. At the time when I write these words a wxPython 2. Browser. Scrollbars are displayed automatically if needed. #!/usr/bin/python # listbox.Add(clr. wx.EXPAND | wx.Bind(wx.EXPAND | wx. size=(90. -1) hbox = wx. 30)) ren = wx.py import wx ID_NEW = 1 ID_RENAME = 2 ID_CLEAR = 3 ID_DELETE = 4 class ListBox(wx. id=ID_RENAME) self.Add(new) vbox.BoxSizer(wx. self.VERTICAL) new = wx. 20)) 0.Bind(wx. they will be default.OnRename) vbox.Button(btnPanel. parent.Add(btnPanel.Add((-1. size=(90.TOP. self.Frame): def __init__(self. id=ID_CLEAR) self. wx.zetcode. To clear all strings in a listbox.Frame. If we put some values there. ID_RENAME.RIGHT. ID_CLEAR. Each of them calls a different method of our listbox.EVT_BUTTON.Panel(panel. 20) btnPanel = wx.Button(btnPanel. vbox.EVT_BUTTON.NewItem.ListBoxNameStr) There is a choices parameter. we call the Clear() method.Window parent. 5) btnPanel. If we want to append a new item. 5) 0.com/wxpython/advanced/ The constructor of a wx. wx. id=ID_NEW) self. title.TOP. title): wx.Add(self.OnRename.Point pos=wx. wx. 220)) panel = wx. vbox. 0. 30)) self. id.Button(btnPanel.Size size=wx. ID_DELETE. -1) hbox. 1. This parameter is empty by In our code example we have a listbox and four buttons. size=(90. id=ID_DELETE) self.Add(ren.__init__(self.DefaultPosition.BoxSizer(wx. 5) 0. string name=wx.listbox. self. we call the Delete() method. parent. ID_NEW. int id=-1. If we want to delete an item. self. 'New'.SetSizer(vbox) hbox.Button(btnPanel.Advanced widgets http://www.OnDelete. displayed from the construction of the widget.HORIZONTAL) self. 30)) clr = wx. -1) vbox = wx. vbox.OnClear. 'Delete'.EVT_LISTBOX_DCLICK. we call the Append() method.Bind(wx.Bind(wx.DefaultValidator.TOP.6.ListBox(wx.Bind(wx.EVT_BUTTON.Panel(self.ListBox widget is as follows: wx.ListBox(panel. self. 30)) dlt = wx. wx. 'Rename'.EVT_BUTTON. id.SetSizer(hbox) 2 de 21 27/04/2008 1:05 .DefaultS list choices=[].listbox = wx. long style=0. 20) panel.ALL. 'Clear'. wx. wx.Validator validator=wx. size=(350. size=(90. wx.Add(dlt. event): sel = self. event): text = wx.GetTextFromUser('Enter a new item'.ALL.GetSelection() if sel != -1: self. event): sel = self.Delete(sel) self.App() ListBox(None. sel) def OnDelete(self. we append it to the def OnDelete(self.Append(text) def OnRename(self.Delete(sel) def OnClear(self.Centre() self.ListBox.Show(True) http://www. the OnRename() method using the wx. This method shows a wx.zetcode. The text that we enter is listbox with the Append() method.EVT_LISTBOX_DCLICK event binder. If the text is not empty. event): text = wx.Bind(wx.Clear() app = wx. self.Advanced widgets self. wx.GetTextFromUser('Enter a new item'.listbox.listbox. def NewItem(self. text) if renamed != '': self.GetSelection() text = self. We put a 20px border around the listbox.Append(text) We call the NewItem() method by clicking on the New button.EVT_COMMAND_LISTBOX_DOUBLE_CLICKED event type with This way we show a rename dialog if we double click on a specific element in the listbox.GetSelection() if sel != -1: self.listbox.MainLoop() self.listbox.Add(self. returned to the text variable. self. 20) We create an empty wx.EVT_LISTBOX_DCLICK. -1. 'Insert dialog') if text != '': self.listbox.OnRename) We bind a wx. 'Insert dialog') if text != '': self.listbox.listbox.GetString(sel) renamed = wx.Insert(renamed.listbox.GetTextFromUser('Rename item'.listbox. 1.listbox.GetTextFromUser dialog window.listbox. 'ListBox') app. event): self.listbox. event): sel = self. -1) hbox. 'Rename dialog'.ListBox(panel.listbox = wx.EXPAND | wx.com/wxpython/advanced/ def NewItem(self.Delete(sel) 3 de 21 27/04/2008 1:05 . HtmlWindow widget. HT M L W I N D OW W I D GET The wx.zetcode. #!/usr/bin/python import wx import wx. event): self.html. This formatting would be very hard if possible to create without wx. wx.Insert(renamed. def OnClear(self. We did this functionality by deleting the previously selected string and inserting a new string into the predecessor's position. Special formatting For example in the following script we will create a window.HtmlWindow widget displays html pages. The parametor to the Delete() method is the selected index.ListBox widget has no Rename() method. A wx. H T M L .listbox.HtmlWindow widget. sel) Notice.listbox. Then we delete the item with the self. item by calling the GetSelection() method. We can do interesting things with wx. how we managed to rename a string.Advanced widgets http://www. We simply call the Clear() method.html.ListBox widget A W X.listbox.Delete(sel) self. It is not a full-fledged browser.html as html ID_CLOSE = 1 4 de 21 27/04/2008 1:05 . that will display basic statistics. First we find the index of the selected Delete() method.com/wxpython/advanced/ Deleting an item is done in two steps.Clear() The easiest thing is to clear the whole listbox.html. parent.Button(panel. 290)) panel = wx. 1. 1.Frame.SetBackgroundColour(wx.Add(htmlwin. -1.App(0) MyFrame(None. self.Close() app = wx. wx.&nbsp. parent.&nbsp.BoxSizer(wx.png')) hbox.RIGHT.Show(True) def OnClose(self.SetPage(page) vbox.EXPAND | wx.Frame): def __init__(self.&nbsp. flag=wx.HORIZONTAL) htmlwin = html.SetStandardFonts() htmlwin.<b>6076</b></td> \ </tr> \ </body></table></html>' class MyFrame(wx. id.TOP.Add((-1.Add(bitmap. title): wx.Minimum</td> \ <td bgcolor="#aaaaaa">&nbsp. 10).&nbsp. 9) bitmap = wx. id.Add(hbox. border=10) vbox. wx.EXPAND | wx.Bitmap('images/newt. title. -1.Panel(self.Advanced widgets http://www.&nbsp. ID_CLOSE.&nbsp.SetSizer(vbox) self. wx.BOTTOM | wx.Add((100.&nbsp.BoxSizer(wx.&nbsp.OnClose.&nbsp. id=ID_CLOSE) hbox. -1. wx. -1) vbox = wx.zetcode.ALL.Bind(wx. 10) buttonOk = wx.NO_BORDER) htmlwin. wx. 0. 1.TOP | wx.Standard Deviation</td> \ <td bgcolor="#aaaaaa">&nbsp.Centre() self. style=wx. -1).Maximum</td> \ <td bgcolor="#aaaaaa">&nbsp.&nbsp.ALIGN_RIGHT) hbox. 'Basic Statistics') app. event): self.com/wxpython/advanced/ page = '<html><body bgcolor="#8e8e95"><table cellspacing="5" border="0" width="250"> \ <tr width="200" align="left"> \ <td bgcolor="#e7e7e7">&nbsp.BOTTOM | wx.<b>3800</b></td> \ </tr> \ <tr align="left"> \ <td bgcolor="#e7e7e7">&nbsp.<b>6000</b></td> \ </tr> \ <tr align="left"> \ <td bgcolor="#e7e7e7">&nbsp.MainLoop() 5 de 21 27/04/2008 1:05 .VERTICAL) hbox = wx.RED) htmlwin.StaticBitmap(panel. size=(400.HtmlWindow(panel.<b>6076</b></td> \ </tr> \ <tr align="left"> \ <td bgcolor="#e7e7e7">&nbsp.Add(buttonOk.EXPAND) panel. 'Ok') self.EVT_BUTTON.Mean</td> \ <td bgcolor="#aaaaaa">&nbsp.LEFT | wx. 0) vbox.__init__(self.Median</td> \ <td bgcolor="#aaaaaa">&nbsp.<b>9000</b></td> \ </tr> \ <tr align="left"> \ <td bgcolor="#e7e7e7">&nbsp. SetForegroundColour('WHITE') hbox = wx. wx. (5.SetBackgroundColour('#6f6a59') header. 1. 5) close = wx. title.Bitmap('icons/help. -1.GetFont() font.py import wx import wx.SetBackgroundColour('#6f6a59') 6 de 21 27/04/2008 1:05 .BOTTOM | wx. The following script will create a help window using the latter idea.AddLabelTool(1. parent.BitmapButton(header. 400)) toolbar = self. #!/usr/bin/python # helpwindow. -1) vbox2 = wx. size=(570.HtmlWindow to provide help in our application.png'. 'Exit'.panelRight = wx.Panel(self. 20)) header.Frame. wx. -1) self.SetFont(font) hbox.Realize() self.Add(st. size=(-1. title): wx. We can create a standalone window or we can create a window.AddLabelTool(2.panelRight. 5)) font = st.panelLeft = wx.SetPointSize(9) st.BORDER_SUNKEN) self. wx.BoxSizer(wx.SplitterWindow(self.HORIZONTAL) st = wx. id. style=wx. 'Help'.Bitmap('icons/fileclose. -1.Panel(self.TOP | wx.NO_BORDER) close.__init__(self. that is going to be a part of the application.com/wxpython/advanced/ Figure: Html window example Help window We can use wx. parent.png')) toolbar.splitter.StaticText(header.splitter.Advanced widgets http://www.Bitmap('icons/exit.BITMAP_TYPE_PNG) style=wx. -1. 'Help'.png')) toolbar.zetcode. wx.Panel(self.html.CreateToolBar() toolbar.LEFT. -1. wx. id.VERTICAL) header = wx.html as html class HelpWindow(wx.BoxSizer(wx.splitter = wx.Frame): def __init__(self. Unsplit() We create left a right panels and split them vertically. we click on the self.OnClose. The header and the body of the text and a bitmap button.splitter.SplitVertically(self.EVT_TOOL.Centre() self. 'HelpWindow') app.EVT_TOOL.panelLeft.Close() def OnHelp(self.panelLeft.EVT_BUTTON.panelRight) self. We put wx.Show(True) def OnClose(self.Unsplit() self.Bind(wx.Bind(wx.GetKeyCode() if keycode == wx.WXK_F1: self. self.com/wxpython/advanced/ help = html. self.panelRight) self.Add(close.CloseHelp.Unsplit() self. The header is an adjusted wx.SetFocus() self. self. To hide the help window.HtmlWindow(self.splitter. 0. wx.panelLeft.App() HelpWindow(None.zetcode.SetFocus() def OnKeyPressed(self. wx.splitter.panelLeft.Bind(wx. self.MainLoop() The help window is hidden in the beginning.OnKeyPressed) self.EXPAND) http://www.html') vbox2. The header consists of a static 7 de 21 27/04/2008 1:05 . we call the Unsplit() method. on the right side of the application. self.panelRight.SetSizer(vbox2) self.splitter.SplitVertically(self.Advanced widgets hbox. 1. event): self.Bind(wx.SetSizer(hbox) vbox2. -1.CreateStatusBar() self.LoadPage('help.Add(help. event): self. id=1) self.Window into the body of the panel.html. id=2) self. By default the method hides the right or bottom panes.splitter.panelRight) self. After that. The help window appears close button. id=close.NO_BORDER) help. self.OnHelp. event): keycode = event.Panel.panelRight.Add(header.splitter.panelRight) self.GetId()) self. panel.panelLeft.SplitVertically(self.EVT_KEY_DOWN.SplitVertically(self.panelLeft. event): self.SetFocus() def CloseHelp(self. We can show it by clicking on the help button on the toolbar or by pressing F1.SetFocus() app = wx. 0) header.panelLeft. style=wx. -1. We divide the right panel into two parts.panelLeft.EXPAND) self. self.splitter. self. HtmlWindow(self. Distributions. -1. event): self. Normality assumption.panelLeft.SetFocus() We set focus on the left panel.LoadPage('help.html. Statistical significance.panelRight) self. This is done in order to make the button appear as a part of the header. because the The following is the html file.SetBackgroundColour('#6f6a59') The bitmap button style is set to wx. def OnHelp(self.panelLeft.html') We create a wx.NO_BORDER) help. <html> <body bgcolor="#ababab"> <h4>Table of Contents</h4> <ul> <li><a <li><a <li><a <li><a <li><a <li><a <li><a </ul> href="#basic">Basic statistics</a></li> href="#advanced">Advanced statistics</a></li> href="#intro">Introducing Newt</a></li> href="#charts">Working with charts</a></li> href="#pred">Predicting values</a></li> href="#neural">Neural networks</a></li> href="#glos">Glossary</a></li> <p> <a name="basic"> <h6>Basic Statistics</h6> Overview of elementary concepts in statistics. We can launch the help window with the F1 key. wx.NO_BORDER.BITMAP_TYPE_PNG). The background color is set to the color of the header panel.png'.Advanced widgets http://www. style=wx. -1. Correlation. wx.zetcode. In order to control a window with a keyboard. We must not forget to set the focus again. </a> 8 de 21 27/04/2008 1:05 . self.NO_BORDER) close.splitter. we call the OnHelp() method. that we load in our application. panels vertically. Variables. self.SplitVertically(self.BitmapButton(header.SetFocus() To show the help window. style=wx.com/wxpython/advanced/ close = wx. Measurement scales.Bitmap('icons/fileclose.HtmlWindow widget on the right panel. it must have the focus.panelLeft.panelRight. We have our html code in a separate file. we would have to first click on the panel and only then we could launch the help window with the F1 key press. This time we call the LoadPage() method to obtain the html code. If we did not set the focus. help = html. It splits the two initial focus is lost by splitting. Linear regression. List of methods.. Exponential smoothing. </a> </p> <p> <a name="neural"> <h6>Neural networks</h6> Overview of neural networks. pie. Preprocessing. Types of neural networks. Seasonality. Exporting data. Biology behind neural networks. 2D charts. Bar. </a> </p> <p> <a name="pred"> <h6>Predicting values</h6> Time series and forecasting. </a> </p> <p> <a name="charts"> <h6>Charts</h6> Working with charts. Training. Univariate methods. Charts. Holt-Winters smoothing. Saving data in various formats. range charts. Fourier analysis. Moving averages. wx. Shortcuts. But wx.HtmlWindow supports only the first one. line.. Multivariate methods. Both are correct html notations.. </a> </p> <p> <a name="intro"> <h6>Introducing Newt</h6> Introducing the basic functionality of the Newt application. ARIMA. <a name="basic"> Normally I would write <div id="basic"> .com/wxpython/advanced/ <p> <a name="advanced"> <h6>Advanced Statistics</h6> Overview of advanced concepts in statistics. Error terms. </div>. Anova.html.zetcode. Basic artificial Model.html. Importing data. Scatterplots. 3D charts. Trend Analysis. Estimation and hypothesis testing. </a> </p> </body> </html> <li><a href="#basic">Basic statistics</a></li> .HtmlWindow supports only a subset of the html markup language.Advanced widgets </p> http://www. 9 de 21 27/04/2008 1:05 . Postprocessing. box. </a> </p> <p> <a name="glos"> <h6>Glossary</h6> Terms and definitions in statistics. Histograms.. Creating sheets. Menus and Toolbars. wx. wx.LC_LIST and wx.zetcode.LC_LIST wx.LC_REPORT.LC_SORT_ASCENDING 10 de 21 27/04/2008 1:05 .ListCtrl styles wx.LC_NO_HEADER wx. wx. wx.ListCtrl.LC_ICON. view or a icon view. -1).LC_ALIGN_LEFT wx.LC_VIRTUAL wx.Window parent.ListCtrl to display directories and files on the file system. These formats are controled by the wx.ListCtrl(wx.LC_SMALL_ICON wx. report wx. int id. A cd burner application displays files to be burned inside a wx. For example a file manager uses a wx.ListCtrl is a very common and useful widget.ListCtrlNa wx. In a list view.LISTCTRL WIDGET A wx.ListBox can only have one column.Validator validator = wx. wx.Size size = (-1.LC_REPORT wx. A wx.LC_ICON. wx.Advanced widgets http://www.com/wxpython/advanced/ Figure: Help window A WX. -1).DefaultValidator.ListCtrl can be used in three different formats. A wx.ListCtrl can have more than one column.Point pos = (-1. int style = wx.ListCtrl window styles. wx.LC_EDIT_LABELS wx.ListCtrl is a graphical representation of a list of items. string name = wx.LC_ICON wx. '1981'). '1949'). ('scarlett johansson'.InsertColumn(0.maxint.LC_HRULES wx. style=wx. -1.EXPAND) panel.Advanced widgets wx. '1984' )] class Actresses(wx. 'london'.LIST_FORMAT_RIGHT. #!/usr/bin/python # actresses. 'new york'. 'name'.list.list = wx. self. -1.list. The default format is wx. 'year'. parent. 90) for i in packages: index = self. wx. 2.ListCtrl with a wx.ListCtrl(panel.LC_REPORT) self. wx. width=140) self.Add(self. 90) We insert three columns.LC_REPORT style. 'actresses') app. ('natalie portman'. ('sigourney weaver'.MainLoop() self.InsertColumn(2. 1. parent. 'jerusalem'.list. 'name'.LC_VRULES http://www.LIST_FORMAT_RIGHT. 11 de 21 27/04/2008 1:05 .list.App() Actresses(None. title. title): wx.__init__(self.list.list. -1.list = wx. size=(380. width=140) self. ('rachel weiss'.ListCtrl. 230)) hbox = wx.py import wx import sys packages = [('jessica alba'.Show(True) app = wx.Panel(self.SetSizer(hbox) self. style=wx.list. 'new york'. 'pomona'. '1975'). i[2]) hbox.InsertColumn(1.Frame.Centre() self. i[1]) self.ListCtrl(panel.InsertColumn(0.InsertColumn(2. 1.SetStringItem(index. width=130) self.InsertColumn(1.list. We can specify the width of the column and the format of the column. width=130) self.LC_REPORT) We create a wx.list.BoxSizer(wx. -1) self. i[0]) self.LIST_FORMAT_LEFT. id. wx.LC_SORT_DESCENDING wx. '1971').zetcode.list.com/wxpython/advanced/ Simple example In the first example we will introduce basic functionality of a wx. '1981').Frame): def __init__(self.InsertStringItem(sys. id. ('angelina jolie'.SetStringItem(index. 'los angeles'. 'place'. 'place'.HORIZONTAL) panel = wx. 'year'. 'london'.TextEditMixin enables text to be edited. -1. This way we can control rows.ListCtrl. ListCtrlAutoWidthMixin): def __init__(self.com/wxpython/advanced/ for i in packages: index = self. ('angelina jolie'.mixins. '1949'). As of 2.lib. '1984' )] class AutoWidthListCtrl(wx.ListCtrl using two methods.zetcode.SetStringItem(index.ListCtrlSelectionManagerMix wx. wx. The method returns the row index.ListCtrlAutoWidthMixin class automatically resizes the last column remaining space.__init__(self) 12 de 21 27/04/2008 1:05 . wx. '1975'). how we can use ListCtrlAutoWidthMixin #!/usr/bin/python # autowidth. 1.Advanced widgets http://www.SetStringItem(index. The following code shows. In order to use them. that each call will insert SetStringItem() method adds data to the consecutive columns of the current Mixins Mixins are classes that further enhance the functionality of a wx.8. Each row begins with a InsertStringItem() method. The first parameter of the method specifies data after the last row. i[0]) self. i[1]) self.InsertStringItem(sys.LC_REPORT) ListCtrlAutoWidthMixin.TextEditMixin wx.ColumnSorterMixin is a mixin that enables sorting of columns in a report to the end of the wx.__init__(self.1. 2. '1971').ListCtrlSelectionManagerMix defines platform independent selection policy. i[2]) We insert data into the wx. By default. style=wx.list. ('scarlett johansson'. 'los angeles'. ('natalie portman'.maxint we ensure.list. The row.CheckListCtrlMixin wx.listctrl module. We can set every row to be checked or unchecked. By giving a sys. the last column does not take the view.mixins.ColumnSorterMixin wx.py import wx import sys from wx. wx.listctrl import ListCtrlAutoWidthMixin actresses = [('jessica alba'.list. the programmer has to There are five available mixins. They are located in inherit from these classes. wx. ('sigourney weaver'. 'new york'. 'pomona'. parent): wx.ListCtrlAutoWidthMixin wx. the row number. See the previous example. '1981'). 'jerusalem'.ListCtrl.1.CheckListCtrlMixin adds a check box to each row.ListCtrl.ListCtrl. parent.lib. ('rachel weiss'.maxint. wx. '1981'). 'new york'. Mixin classes are so called helper classes. wx. parent. -1) self.InsertColumn(2. title): wx. 'place'. 90) for i in actresses: index = self. 2. ListCtrlAutoWidthMixin): def __init__(self. This is called multiple inheritance.list. wx.maxint. wx.lib.Frame. 1. style=wx.ListCtrl. from wx.EXPAND) panel.Advanced widgets http://www. -1.Add(self. parent.MainLoop() We change the previous example a bit. 'name'.list. class AutoWidthListCtrl(wx. 'actresses') app.list.__init__(self. The last column will automatically resize to take up the remaining width of a wx. -1. 13 de 21 27/04/2008 1:05 .ListCtrl and ListCtrlAutoWidthMixin. i[2]) hbox.Show(True) app = wx.Centre() self.BoxSizer(wx.SetStringItem(index. i[0]) self.listctrl import ListCtrlAutoWidthMixin Here we import the mixin. id.list.LIST_FORMAT_RIGHT. title. width=140) self. This class will inherit from wx.App() Actresses(None.Panel(self.HORIZONTAL) panel = wx. 230)) hbox = wx. size=(380.list = AutoWidthListCtrl(panel) self.list. width=130) self. 'year'.__init__(self. i[1]) self.SetSizer(hbox) self. parent.list. 1.mixins.ListCtrl.LC_REPORT) ListCtrlAutoWidthMixin. id.Frame): def __init__(self.InsertColumn(1.com/wxpython/advanced/ class Actresses(wx.SetStringItem(index.zetcode.InsertColumn(0.__init__(self) We create a new AutoWidthListCtrl class.list. parent): wx.InsertStringItem(sys.ListCtrl. size=(380.ListCtrl.BoxSizer(wx.ListCtrl. ColumnSorterMixin): def __init__(self. 6 : ('scarlett johansson'. #!/usr/bin/python # sorted.listctrl import ColumnSorterMixin actresses = { 1 : ('jessica alba'. 'new york'. 'london'. 90) items = actresses. 'year'. -1.InsertColumn(1.itemDataMap = actresses def GetListCtrl(self): return self class Actresses(wx.py import wx import sys from wx. parent): wx. 230)) hbox = wx. width=140) self. 'name'.mixins.items() for key. 'pomona'. '1981'). '1981'). 'los angeles'.__init__(self. 'new york'. how we can create sortable columns. 5 : ('rachel weiss'. If we click on the column header.list = SortedListCtrl(panel) self.LIST_FORMAT_RIGHT.HORIZONTAL) panel = wx. 3 : ('angelina jolie'.list.InsertColumn(2.Advanced widgets http://www.list.LC_REPORT) ColumnSorterMixin. '1949').Frame): def __init__(self. 2 : ('sigourney weaver'.list. the corresponding rows in a column are sorted. 4 : ('natalie portman'. data in items: 14 de 21 27/04/2008 1:05 . -1) self. wx. style=wx. id.__init__(self. 'place'. parent. '1971').InsertColumn(0. parent. len(actresses)) self.zetcode. title): wx.Frame. parent. title. 'jerusalem'. '1984') } class SortedListCtrl(wx.lib.com/wxpython/advanced/ Figure: AutoWidth example In the following example we will show.__init__(self. id. width=130) self.Panel(self. '1975'). EXPAND) panel. ['Gnome pretty. 'The year of the Mozilla'.InsertStringItem(sys.Centre() self.list.list. ['Java number one language'.list. -1.SetSizer(hbox) self. 'Compiled languages. This method returns the wx. intrepreted Languages'. 'actresses') app.SetStringItem(index.list. data[2]) self. def GetListCtrl(self): return self We must create a GetListCtrl() method. 1. 'Earth on Fire'].com/wxpython/advanced/ index = self.SetStringItem(index.Show(True) app = wx.list. ColumnSorterMixin. The data must be in a dictionary data type. data[0]) self. data[1]) self.SetItemData(index. Reader A reader is a complex example showing two list controls in a report view. It is the number of columns to be sorted.MainLoop() We will again use the example with actresses. wx. 'Gnome. Icewm. KDE. 1. Gnome Slow'. self. #!/usr/bin/python # reader.maxint.ListCtrl widget that is going to be sorted. XFCE'.Add(self.itemDataMap = actresses We must map our data to be displayed in a list control to the itemDataMap attribute. key) We must assosiate each row with a special index.__init__(self.list. self.SetItemData(index.zetcode.py import wx articles = [['Mozilla rocks'. This is done with the SetItemData method.Advanced widgets http://www. 'Where is Gnome heading?']. len(actresses)) The ColumnSorterMixin accepts one argument.App() Actresses(None. key) hbox. 2. 'Java on D 15 de 21 27/04/2008 1:05 . LC_SINGLE_SEL) images = ['icons/java.png'. id. id.SetImageList(self. parent.ListCtrl.SetColumnWidth(0.EVT_SIZE.Bitmap(i)) self. '') for i in range(3): self. event): size = self.GetIndex() window. event): self. parent. parent. parent.parent = parent self.SetColumnWidth(0. 'icons/gnome.Frame.LC_HRULES | wx. size.__init__(self.parent.InsertColumn(0.LC_NO_HEADER | wx.SetItemBackgroundColour(index. 32) for i in images: self.OnSelect) self.EVT_SIZE.InsertColumn(0.Bind(wx.com/wxpython/advanced/ class ListCtrlLeft(wx. id): wx.GetSize() self.LoadData(index) def OnDeSelect(self.parent = parent self.OnSize) self. articles[index][i]) class Reader(wx.LC_HRULES | wx.Bind(wx. '') self.OnSize) self. self.ListCtrl): def __init__(self.il. title) 16 de 21 27/04/2008 1:05 . index): self.__init__(self.ListCtrl.Skip() def LoadData(self. id.ImageList(32.x-5) event. event): window = self.il = wx. self.GetIndex() self.SetItemBackgroundColour(0.FindWindowByName('ListControlOnRight') index = event.IMAGE_LIST_SMALL) self.png'. style=wx. event): size = self.LC_SINGLE_SEL) self. wx.SetItemImage(0. 'WHITE') def OnFocus(self. event): index = event.GetSize() self.png'] self.Add(wx.__init__(self.EVT_LIST_ITEM_SELECTED.parent.InsertStringItem(0. i) def OnSize(self. title): wx. self. id.LC_REPORT | wx. 'icons/mozilla. id): wx.x-5) event. '') def OnSize(self.DeleteAllItems() for i in range(3): self.LC_NO_HEADER | wx.zetcode. style=wx.Advanced widgets http://www.LC_REPORT | wx.ListCtrl): def __init__(self.parent.Bind(wx.InsertStringItem(0.GetGrandParent().il. size. parent.Skip() def OnSelect(self.Frame): def __init__(self. 'red') class ListCtrlRight(wx. parent. SP_NOBORDER) vbox1 = wx. -1) list2.Panel(panel2.Add(panel22. 40). -1) panel11 = wx. wx. 1.EXPAND) panel22.EXPAND) panel2. 1.StaticText(panel21. 0.EXPAND) panel1.Add(splitter. -1. style=wx.Panel(panel1. 1.AddLabelTool(1. 'Exit'.png')) toolbar.CreateToolBar() toolbar.SetBackgroundColour('WHITE') vbox2. -1. -1) vbox.SetSizer(vbox3) panel22.ExitApp.Close() app = wx. self.EXPAND) vbox1. 5)) st1. id=1) hbox.BoxSizer(wx.SetForegroundColour('WHITE') panel21.Add(panel12. -1.StaticText(panel11.SetBackgroundColour('WHITE') vbox1. 5) self. wx. 'Reader') app.CreateStatusBar() splitter.Add(panel21. wx.HORIZONTAL) splitter = wx.VERTICAL) list2 = ListCtrlRight(panel22. -1.TOP | wx.VERTICAL) panel2 = wx. wx.zetcode.SplitterWindow(self.BoxSizer(wx.App() Reader(None.com/wxpython/advanced/ hbox = wx.Add(panel11. 5)) st2. -1.Show(True) def ExitApp(self. wx. size=(-1. style=wx.EVT_TOOL.SetBackgroundColour('#53728c') panel22 = wx. panel2) self.Panel(panel2.MainLoop() 17 de 21 27/04/2008 1:05 . 1. style=wx.Realize() self. 0.BORDER_SUNKEN) vbox = wx.SetSizer(vbox1) vbox2 = wx.BoxSizer(wx.VERTICAL) list1 = ListCtrlLeft(panel12.EXPAND) panel12. size=(-1. 'Articles'. 'Feeds'.BoxSizer(wx.Panel(splitter.NO_BORDER) st2 = wx.SetSizer(vbox2) toolbar = self.VERTICAL) panel1 = wx.Centre() self. (5.Add(list2.SetForegroundColour('WHITE') panel12 = wx. -1. 40)) panel11.EXPAND) vbox2. event): self. -1.SetName('ListControlOnRight') vbox3. 1.EXPAND | wx.SP_LIVE_UPDATE|wx.SetSizer(vbox) panel12.Panel(panel1.BORDER_RAISED) vbox3 = wx.Panel(splitter.Add(list1.SetSizer(hbox) self. (5.Bind(wx.SetBackgroundColour('#53728c') st1 = wx.BoxSizer(wx.BOTTOM. wx.SplitVertically(panel1. style=wx. -1. wx. -1) panel21 = wx. wx.Bitmap('icons/stock_exit.Advanced widgets http://www. Here we ensure that the size of the column equals to size of the parent panel.SetName('ListControlOnRight') When we create ListCtrlRight object..parent.SplitVertically(panel1. def OnSize(self.SetColumnWidth(0.SplitterWindow(self. number.parent. Those two panels will have another two panels. We show two wx.ListCtrl in a report view.ListCtrl widgets.InsertStringItem(0. event): window = self. we give it a name ListControlOnRight.com/wxpython/advanced/ One is on the right side and the other one on the left side of the application. This is because we need ListCtrlRight and ListCtrlLeft two widgets to communicate. index): self. event): size = self.ListCtrl widgets.ListCtrls have only one column. The application would not look nice otherwise.Skip() Both wx. -1) list2.SP_NOBORDER) .LoadData(index) This code is in ListCtrlLeft class.Advanced widgets http://www.FindWindowByName('ListControlOnRight') index = event. panel2) The splitter will split the main window into two vertical parts.DeleteAllItems() for i in range(3): self. create Feeds and Articles headers. We shall create our own headers. Here we locate the ListCtrlRight object and call it's LoadData() method. splitter. The splitter will show two panels. articles[index][i]) The LoadData() method first clears all items. def OnSelect(self.GetIndex() window. -1. size.zetcode. The previous example showed a wx. Then it inserts the article names from the globally defined articles list. style=wx. With no splitter = wx. Why do we extract 5px? This number is a kind of magic other platforms.GetSize() self. def LoadData(self. They our two wx.SP_LIVE_UPDATE|wx. If we extract exactly 5px.. The rest of the space will be occupied by list2 = ListCtrlRight(panel22. The index has been passed. the number might be different. the horizotal scrollbars do not appear.x-5) event. headers. On 18 de 21 27/04/2008 1:05 .GetGrandParent(). HORIZONTAL) leftPanel = wx. Checked and unchecked. The code is in CheckListCtrlMixin.ListCtrl. -1) self. style=wx. 'base').com/wxpython/advanced/ Figure: Reader CheckListCtrl It is quite common to see applications having check boxes inside list controls. For both situations we have a #!/usr/bin/python # repository. unique image. CheckListCtrlMixin. style=wx. -1) rightPanel = wx.zetcode.__init__(self) ListCtrlAutoWidthMixin. 'base'). ('ash'. parent. '71k'. id.Panel(panel. 'base'). ('ascii'.Panel(self. -1) vbox = wx.BoxSizer(wx. title.mixins. '74k'. -1. '5. parent): wx. '74k'.LC_REPORT | wx.8M'. parent.py import wx import sys from wx.ListCtrl. those checkboxes are simple images.BoxSizer(wx.TextCtrl(rightPanel. 400)) panel = wx. It has been already coded.VERTICAL) hbox = wx. parent.lib.listctrl import CheckListCtrlMixin.Frame. '5.log = wx. 'base'). 'base').__init__(self) class Repository(wx. id.TE_MULTILINE) 19 de 21 27/04/2008 1:05 . '145k'. 'base')] class CheckListCtrl(wx. ('ara'.Panel(panel. From the programmer's point of view. ('asc'. ('arc'. title): wx. There are two states. 'base').Frame): def __init__(self. We do not have to implement the functionality.SUNKEN_BORDER) CheckListCtrlMixin. ListCtrlAutoWidthMixin): def __init__(self. '717k'. -1. '139k'.__init__(self.__init__(self. size=(450. ('airsnort'.Advanced widgets http://www. 'base'). ListCtrlAutoWidthMixin packages = [('abiword'. For example a packaging application like Synaptic or KYUM. ('adie'.8M'. width=140) self.list. 0.OnSelectAll.Add(sel.EXPAND) vbox. wx. 5) hbox.list. 10)) vbox.Button(leftPanel. self.InsertColumn(1.IsChecked(i): self.TOP. False) def OnApply(self.zetcode.Bind(wx.list.MainLoop() 20 de 21 27/04/2008 1:05 .Advanced widgets http://www.GetId()) self. 1. wx.SetSizer(hbox) self.Clear() if self.maxint.SetStringItem(index. -1)) panel.Button(leftPanel.EVT_BUTTON.AppendText(self.CheckItem(i.Add((-1. id=des. id=apply.GetItemCount() for i in range(num): self.Show(True) def OnSelectAll(self. -1. i[1]) self. id=sel.Add(self. event): num = self.log.Bind(wx.list.log. 'Size') self.OnDeselectAll.InsertColumn(2.Add((-1.Add(rightPanel.OnApply. 0. self.EXPAND | wx.InsertStringItem(sys. 'Deselect All'.list. size=(100. 'Repository') for i in packages: index = self.5.EVT_BUTTON.CheckItem(i) def OnDeselectAll(self. 1.GetId()) self.log.Add(leftPanel. -1)) apply = wx.Bind(wx.Add(des) vbox2.list.EXPAND | wx. 'Repository') app.BoxSizer(wx.SetStringItem(index.TOP. -1. wx. -1)) des = wx.SetSizer(vbox) hbox.GetItemText(i) + '\n') app = wx.GetId()) vbox2. 'Select All'. event): num = self. 5) vbox2.list. i[0]) self.Centre() self.Button(leftPanel. 10)) rightPanel.InsertColumn(0.list.GetItemCount() for i in range(num): self.list. size=(100. 'Apply'.Add(self. -1. event): num = self. 1.list.Add((3.list. wx.App() Repository(None.list. 2.list. i[2]) vbox2 = wx. self.GetItemCount() for i in range(num): if i == 0: self.VERTICAL) sel = wx. wx.com/wxpython/advanced/ self.EVT_BUTTON.EXPAND) hbox. 0.list. 'Package'. 3) vbox.RIGHT. -1.list = CheckListCtrl(rightPanel) self. -1)) self. size=(100.Add(apply) leftPanel.SetSizer(vbox2) vbox. CheckItem(i) Here we can see multiple inheritance in action. style=wx. Free XML (XSL) tutorial.GetItemCount() for i in range(num): self. free.LC_REPORT | wx. We can call two methods method is located in CheckListCtrl class and the CheckItem() method is in from two different classes on our self.list object.list.__init__(self. XSL Tutorial.zetcode. def OnSelectAll(self. 2007 © 2007 Jan Bodnar 21 de 21 27/04/2008 1:05 .SUNKEN_BORDER) CheckListCtrlMixin. CheckListCtrlMixin.Advanced widgets http://www. XML/XSL Genuine python handbags on sale We to PDF. The GetItemCount() CheckListCtrlMixin class. Light. Here we inherit from three different classes. Print converter Custom make handbag for you Python Purse on sale Home ‡ Contents ‡ Top of Page ZetCode last modified June 3.__init__(self) wxPython enables multiple inheritance.com/wxpython/advanced/ Figure: Repository class CheckListCtrl(wx.ListCtrl. parent.ListCtrl. ListCtrlAutoWidthMixin): def __init__(self.__init__(self) ListCtrlAutoWidthMixin. event): num = self. samples.list. parent): wx. -1. FileDropTarget.py 1 de 3 27/04/2008 1:05 . In general. Debugger. Easier Python Development Editor. drag-and-drop is the action of (or support for the action of) clicking on a virtual object and dragging it to a different location or onto another virtual object. So we must have: Some data A data source A data target In wxPython we have two predefined data targets. it can be used to two abstract objects.NET Drag drop and node editing support Drag and drop in wxPython Wikipedia: In computer graphical user interfaces. wx.zetcode.FileDropTarget wx. wx. or create various types of associations between Drag and drop functionality is one of the most visible aspects of the graphical user interface. invoke many kinds of actions.TextDropTarget and wx.TextDropTarget Figure: dragdrop.NET TreeView Advanced TreeView for ASP.com/wxpython/draganddrop/ Python IDE Home Contents Faster. In drag and drop we basically drag some data from a data source to a data target.Drag and drop in wxPython http://www.TextDropTarget wx. Drag and drop operation enables you to do complex things intuitively. Browser. and more ASP. com/wxpython/draganddrop/ #!/usr/bin/python # dragdrop. title): wx. On the other hand.GetItemText(event.SP_3D) self. id=tree.OnSelect(0) self.EVT_TREE_SEL_CHANGED.Frame): def __init__(self.lc1.DIRCTRL_DIR_ONLY) self. parent.object = object def OnDropText(self.Centre() self.object. data): self.ClearAll() for i in range(len(list)): if list[i][0] != '.lc2 = wx.lc1) tds. style=wx. object): wx.GetTreeCtrl() splitter2. self.__init__(self.OnDragInit.lc1 = wx. y.lc2) splitter1. self. event): list = os. event): text = self. style=wx.LC_LIST) self.lc2) self. For 2 de 3 27/04/2008 1:05 .Bind(wx.SetDropTarget(dt) self. id.lc1.FileDropTarget One of the advantages of the GUI over the console is it's intuitiveness. style=wx.py') app.ListCtrl(splitter2.SP_3D) splitter2 = wx.SplitterWindow(splitter1.GetId()) self.GetPath()) self.MainLoop() wx. dir='/home/'.OnSelect.SetData(tdo) tds.TextDropTarget.GetId()) tree = self. some graphical operations are too complex.LC_LIST) dt = MyTextDropTarget(self. list[i]) def OnDragInit(self.GetIndex()) tdo = wx.Drag and drop in wxPython http://www.InsertStringItem(0.Show(True) def OnSelect(self.py import os import wx class MyTextDropTarget(wx.DropSource(self. style=wx. style=wx.EVT_LIST_BEGIN_DRAG.lc1.InsertStringItem(0. 500)) splitter1 = wx.Bind(wx. self. 'dragdrop. -1. x. -1. -1.ClearAll() self.lc2. id. -1.listdir(self.TextDropTarget): def __init__(self.dir. -1. You often do not need a manual.TextDataObject(text) tds = wx.SplitterWindow(self. -1.dir.__init__(self) self.dir.dir = wx. id=self. size=(650. title.zetcode.': self.lc1. You can learn a GUI program easier than a console application. splitter2) self.ListCtrl(splitter2. parent.lc2.GenericDirCtrl(splitter1.App() DragDrop(None. data) class DragDrop(wx.DoDragDrop(True) app = wx.Frame.SplitHorizontally(self.lc1.SplitVertically(self. text. title. error: dlg = wx.text = wx.window. that is very handy. In our next example we explore a graphical operation. id. id. filenames): for name in filenames: try: file = open(name.py import wx class FileDrop(wx. y.WriteText(text) file.Show(True) app = wx.ShowModal() except UnicodeDecodeError.window = window def OnDropFiles(self.Centre() self.FileDropTarget. 2007 © 2007 Jan Bodnar 3 de 3 27/04/2008 1:05 .text) self. error: dlg = wx.egenix.TE_MULTILINE) dt = FileDrop(self. 'Error opening file\n' + str(error)) dlg. 'r') text = file.com/wxpython/draganddrop/ example. size = (450. parent. -1. (shift + delete) It is more effective. deleting a file by dragging it and droping it to the trash basket is very intuitive and easy to understand.MessageDialog(None. parent.ShowModal() class DropFile(wx. title): wx. .Net/C#. style = wx.com Home ‡ Contents ‡ Top of Page ZetCode last modified June 28.App() DropFile(None.__init__(self.MessageDialog(None. mxodbc. In most GUI text editors. #!/usr/bin/python # filedrop. x.zetcode.MainLoop() eXtreme Programming Assistance Technique Java/J2ee.Frame): def __init__(self. Python. you can open a file by simply dragging it from the file manager and dropping it on the editor.Frame.__init__(self) self.py') app.read() self. 'Cannot open non ascii files\n' + str(error)) dlg. -1.FileDropTarget): def __init__(self. 400)) self. but actually most people just press the delete key.close() except IOError.TextCtrl(self. Ruby Python Database Interface Easily connect Python to all your databases. window): wx.Drag and drop in wxPython http://www.SetDropTarget(dt) self. 'filedrop. If we want to create and use wxPython applications in languages other than english. and more Free PHP Examples Edit & Debug Your PHP Applications Learn PHP by Example with PhpED Internationalization In computing. that in the example. Debugger. It is a character enconding standart which uses 16 bits for storing characters.zetcode. The ansi build and the unicode build.com/wxpython/in18/ Python IDE Home Contents Faster. Browser.Internationalization http://www. Localization is the process of adapting the software to be as familiar as possible to a specific locale. First. Internationalization and localization are means of adapting computer software for non-native environments. The traditional ASCII enconding uses only 8 bits. (wikipedia) displaying text in the local language and using local conventions Unicode There are two builds of wxPython. Notice. Internationalization is the local requirements. we must have the unicode build. by for the display of such things as units of measurement. we use additional \n\ characters to divide the words into two lines. we need to get the unicode enconding of Лев Николaевич Толстoй Анна Каренина words. Easier Python Development Editor. >>> unicode(u'Лев Николaевич Толстoй Анна Каренина') u'\u041b\u0435\u0432 \u041d\u0438\u043aa\u0430\u0301\u0435\u0432\u0438\u0447 \u0422\u043e\u043b\u0441o\u0439 \u0410\u043d\u043d\u0430 \u041a\u0430\u0440\u0435\u043d\u0438\u043d\u0430' We launch the python terminal and use the unicode() function call. #!/usr/bin/python 1 de 12 27/04/2008 1:06 . for instance ensuring that the local writing process of ensuring that an application is capable of adapting to system can be displayed. especially other nations and cultures. Unicode is an industry standard allowing computers to consistently represent and manipulate text expressed in any of the world's writing systems. Figure: Unicode Locale A locale is an object that defines user's language. title. event): dc = wx. -1.codeset][@modifier]] 2 de 12 27/04/2008 1:06 .Frame. size=(250.Centre() self. 'Unicode') app. self.DrawText(text. id.App() Unicode(None.PaintDC(self) dc. parent.com/wxpython/in18/ import wx text = u'\u041b\u0435\u0432 \u041d\u0438\u043a\u043e\u043b\u0430\ \u0435\u0432\u0438\u0447 \u0422\u043e\u043b\u0441\u0442\u043e\u0439 \n\ \u0410\u043d\u043d\u0430 \u041a\u0430\u0440\u0435\u043d\u0438\u043d\u0430' class Unicode(wx.Show(True) def OnPaint(self.zetcode. number format. [language[_territory][. parent. 50.MainLoop() In the example.Internationalization http://www. 150)) self.EVT_PAINT. letter format. 50) app = wx. id.OnPaint) self. we draw Anna Karenina in russian azbuka on the window. A local variant has the following format. currency format etc.__init__(self. country.Frame): def __init__(self.Bind(wx. title): wx. (25. 220)) 'currency: '. 'UTF8')) date = time.StaticLine(self. 200)) 'time: '. 90)) wx. -1.StaticText(self. wx. 'date: '. (125.StaticLine(self. 200)) time_.__init__(self. 150)) de.Panel(self. 110)) wx. de_AT. str(time_).setlocale(locale.SetFont(font) wx. str(date). wx. -1. -1. (25. (25. 'United States'.py import wx import time import locale class Locale(wx.strftime('%X'.Internationalization http://www. tm) time_ = time. -1. -1. (25.localtime() font = wx.com/wxpython/in18/ For example. 70)) wx. -1. 240)) 3 de 12 27/04/2008 1:06 .StaticText(self. 110)) de = wx.StaticText(self.setlocale(locale.StaticText(self. -1. ('de_DE'. wx. id. 420)) panel = wx. parent. (125.strftime('%x'. -1. 180).1)) locale. (25. size=(250. wx. (200. 90)) wx. wx. (25.StaticText(self. parent.StaticText(self.StaticText(self. -1. 'time: '.Frame): def __init__(self. 240)) date.Frame.StaticText(self. (125. -1. title): wx.strftime('%x'. 50). (200 . tm) time_ = time. (125.Font(10. (25. str(curr). 'currency: '.1)) locale. (25. 70)) wx. 220)) curr. (125. tm) curr = locale. #!/usr/bin/python # locale. '') date = time. -1. tm) curr = locale.currency(100000) wx.StaticText(self. wx.StaticText(self.zetcode. 'date: '. (25. wx. 'Germany'. title.currency(100000) wx.StaticText(self.LC_ALL.StaticText(self. with UTF8 codeset. -1.NORMAL. -1.StaticText(self. 20)) us. -1.LC_ALL. (25.SetFont(font) wx. -1.BOLD) us = wx.strftime('%X'.utf8 is a german local used in Austria. -1.StaticText(self. -1) tm = time. wx. id.DEFAULT. (125. 1)) locale. we will show various formats of date. tm) time_ = time. (25. 370)) wx. (125. 'UTF8')) Here we set a locale object for Germany.MainLoop() localized settings. 280)) de.g.setlocale(locale. (25. ('de_DE'.currency(100000) wx. tm) curr = locale. -1. We use the standart built-in module locale to work with locale. 'Slovakia'. -1. tm) curr = locale. -1.setlocale(locale. LC_ALL is a LC_MONETARY.StaticText(self.StaticText(self.zetcode. -1. LC_TIME. Germany and Slovakia.App() Locale(None.StaticText(self.strftime('%X'. -1.StaticText(self. 350)) wx.Show(True) app = wx. (25.com/wxpython/in18/ de = wx. 'time: '. 350)) wx.strftime('%X'.StaticText(self. 'UTF8')) date = time. -1.StaticLine(self.strftime('%x'. -1. 370)) self. 'Locale') app. 'date: '. ('sk_SK'.SetFont(font) wx. time and currency in the USA. LC_NUMERIC. 'currency: '. str(curr). e. str(time_).StaticText(self. 330)) wx. 310). -1. (25.Internationalization http://www.Centre() self. -1. (125. str(date). 330)) wx. tm) time_ = time.LC_ALL. In our example. date = time. (200. (25. combination of all various local settings. 4 de 12 27/04/2008 1:06 .StaticText(self.strftime('%x'.currency(100000) These function calls reflect the current locale object.LC_ALL. (125. 280)) self.com/wxpython/in18/ Figure: Locale World Time At a specific moment.panel. parent.Frame): def __init__(self. -1) self. wx.Panel(self.__init__(self. It is not comes with a wx.FONTSTYLE_NORMAL. According to the uncommon for programmers to deal with such tasks.DateTime object. #!/usr/bin/python import wx import time class WorldTime(wx. parent.panel = wx. title. we have different time in countries across the world.Frame.Font(12.zetcode.FONTWEIGHT_BOLD. id. wx.FONTFAMILY_DEFAULT. wxPython documentation.Internationalization http://www.SetBackgroundColour('#000000') font = wx. 'Georgia') 5 de 12 27/04/2008 1:06 . title): wx. wx. Our globe is divided into time zones. wxDateTime class represents an absolute moment in the time. id. False. size=(270. DateTime() self. (20.App() WorldTime(None.tokyo.SetForegroundColour('#23f002') self.MainLoop() In the code example.SetLabel('London: ' + str(now.Bind(wx.london.SetLabel('Budapest: ' + str(now.SetFont(font) self.budapest.zetcode.london = wx. Moscow.panel.EDT))) app = wx. -1. -1. wx.budapest. wx. self. 170)) self.SetForegroundColour('#23f002') self. self.Start(1000) self.newyork.moscow = wx.SetLabel('Moscow: ' + str(now.budapest.panel.Format(('%a %T').timer.tokyo. -1.Centre() self.dt.dt.dt.FormatTime() . evt): now = self.DateTime.timer = wx.FormatTime() .SetForegroundColour('#23f002') self. 20)) self.Format(('%a %T').moscow.StaticText(self.Now() self.Timer(self) self.newyork. self.DateTime.budapest = wx.SetForegroundColour('#23f002') self.DateTime.Format(('%a %T').FormatTime() . self.SetLabel('New York: ' + str(now. 120)) self.DateTime.panel.StaticText(self.OnTimer(None) self.DateTime.london.panel.SetLabel('Tokyo: ' + str(now. 70)) self. Budapest.StaticText(self. -1.com/wxpython/in18/ self. wx. (20. -1. (20. (20.StaticText(self.OnTimer) self. we show current time in Tokyo. self.dt.Show(True) def OnTimer(self.dt. (20.WEST))) self.SetFont(font) self.SetForegroundColour('#23f002') self.newyork.Format(('%a %T'). wx. 6 de 12 27/04/2008 1:06 .EVT_TIMER.FormatTime() .moscow.Format(('%a %T'). -1.dt.london.SetFont(font) self.MSD))) self.panel.moscow.tokyo = wx. 220)) self.SetFont(font) self.FormatTime() .CEST))) self.Internationalization http://www.dt = wx.GMT_9))) self.SetFont(font) self. 'World Time') app. wx.StaticText(self.newyork = wx. London and New York. self.tokyo. The code example was checked with the timeanddate. 7 de 12 27/04/2008 1:06 . The second parameter for Japan.SetLabel('Tokyo: ' + str(now.DateTime() Here we create a wx.DateTime object. The %T is the time of day using decimal conversion specifier is an abbreviated weekday name according numbers using the format %H:%M:%S. EDT (Eastern Daylight Saving Time) is used in New York etc.dt. of the Format() method specifies the time zone.Format(('%a %T').com Figure: World Time Sorting Locale settings also affect the way.GMT_9))) This code line sets the time to the appropriate format.tokyo.Now() We get the "absolute moment" in time.dt = wx. GMT_9 is used website. The %a to the current locale.zetcode. self. now = self.DateTime. wx. how strings are being sorted.Internationalization http://www.com/wxpython/in18/ self. ('de_DE'.BoxSizer(wx. 20) panel. parent.b: locale.App() Collate(None.com/wxpython/in18/ For example hungarian language has some characters that are have accents. title): wx.ListBox(panel.SetSizer(vbox) hbox.EXPAND | wx.Add(btnPanel. 20) btnPanel = wx. wx. parent.Internationalization http://www. u'S\xe4bel'. 0.py import wx import locale ID_SORT = 1 words = [u'Sund'.Add(self. self.Frame.LC_COLLATE.Button(btnPanel. 'Sort'.HORIZONTAL) self.EVT_BUTTON. 220)) panel = wx.RIGHT. id=ID_SORT) vbox.listbox = wx.Add(new) btnPanel.MainLoop() 8 de 12 27/04/2008 1:06 . b) ) for i in words: self. u'Schl\xe4fe'.listbox. id. 30)) self.Panel(self. -1) vbox = wx.EXPAND | wx.ALL.listbox. Some languages #!/usr/bin/python # collate.BoxSizer(wx.__init__(self.Add((-1. 'Collate') app.sort( lambda a. ID_SORT.listbox.zetcode.Append(i) app = wx.VERTICAL) new = wx. -1) for i in words: self. u'Sabotage'] class Collate(wx.Append(i) hbox.OnSort.Panel(panel. others don't. 'UTF8')) self.Bind(wx. wx.Frame): def __init__(self.listbox.setlocale(locale. u'S\xfcnde'. size=(300. title.Clear() words. -1) hbox = wx. event): self.strcoll(a.Centre() self. missing in Slovak language or English language. size=(90.SetSizer(hbox) locale. id. -1. 1.Show(True) def OnSort(self. 20)) vbox.6. german alphabet ä character precedes a character. 0. the default one. we must use locale functions. but it takes the locale settings (the collate) into Figure: Collate Simple Translation In the following example. ('de_DE'. Either to use the GNU gettext or to use the wxPython catalogs.com/wxpython/in18/ In our example.zetcode. 1 exactly like account.setlocale(locale.Internationalization http://www. We define an anonymous lambda function.Locale.strcoll(a. We could use the LC_ALL option or the more specific LC_COLLATE one. words. because in corect sorting. wxPython has a class wx. This is incorrect. b) ) The trick is to use a new compare function within the sort() function. To get the locale. Säbel. Schläfe. we took 5 germam words from the dictionary. Both systems are compatible. This way we have the correct sorting of words. The strcoll() function compares two strings and returns -1. A programmer has two options. which is a base for using 9 de 12 27/04/2008 1:06 .sort( lambda a. Sünde. The default sort() function sorts these words this way: Sabotage.b: locale. Sund.LC_COLLATE. we will demonstrate a very basic translation. 'UTF8')) Here we set the german collate. Frame): def __init__(self.utf8 en_DK. Notice for working with strings.utf8 en_IE. parent. First.Locale() mylocale.Frame.utf8 en_SG.utf8 en_US. English language and german language have different dialects. -1) mylocale = wx. We put the string that are to be translated into this _(). 100)) panel = wx.utf8 en_IN en_NZ.__init__(self.utf8 de_CH.utf8 To check what languages are supported.utf8 en_PH.utf8 de_BE. the utf8 string.utf8 POSIX sk_SK. title.Internationalization http://www. german and slovak language support. we want to translate a string into german language. we must ensure. Say. id.utf8 en_GB. or we can use the wx. that we have language support for german language.Panel(self.utf8 de_DE. size=(220. id. This means. #!/usr/bin/python import wx class Translation(wx.GetTranslation() call.utf8 de_LU. parent.') 10 de 12 27/04/2008 1:06 .utf8 en_CA. Each translation has one catalog. title): wx.com/wxpython/in18/ message catalogs.AddCatalogLookupPathPrefix('.utf8 en_HK.utf8 en_ZW. $ locale -a C de_AT. On my system.utf8 en_AU.utf8 en_BW.utf8 en_ZA. I have english. that the system uses utf8 encoding Next we write our code example. that's why we have so many options.zetcode. we use the locale command. The last thing we do is to create a binary message catalog.po simple. wx. -1. 'Translation') app.Show(True) app = wx. 11 de 12 27/04/2008 1:06 . (10. 10)) self.GetTranslation('hello').AddCatalog('simple_de') _ = wx. We must specify the charset.MainLoop() Next we create a so called PO file.py To create a po file. To fully understand the format of the po file.po file. consult the gnu gettext manual. which is translators use to translate the strings.StaticText(panel. "Content-Type: text/plain. charset=utf-8\n" We edit the simple_de.GetTranslation wx. (10.py:17 msgid "hello" msgstr "Grüß Gott" Here we provide a translation for the hello string.zetcode. -1.po To produce a mo file. It is a simple text file. In our case it is utf-8.Internationalization http://www. pygettext -o simple_de. _("hello").mo simple_de.com/wxpython/in18/ mylocale.Centre() self. #: simple. we use the pygettext command. msgfmt --output-file simple_de.App() Translation(None. we call the msgfmt command. 10)) #wx.StaticText(panel. -1. Internationalization http://www.zetcode.com/wxpython/in18/ Figure: Simple translation Governance/Participation Python Purse on sale Non-state actors, parliament and governments in ACP-EU cooperation Genuine python handbags on sale We Custom make handbag for you Home ‡ Contents ‡ Top of Page ZetCode last modified October 8, 2007 © 2007 Jan Bodnar 12 de 12 27/04/2008 1:06 Working with databases http://www.zetcode.com/wxpython/databases/ Home ContentsShows DeviceSQL Faster, Benchmark Report Smaller. Get the Facts. 5x Faster than SQL lite Embedded Sql Database Free Webinar: Choosing an Embedded Relational Database Working with databases Database driven applications account for a large part of all applications ever developed. And they will definitely in the future as well. Most of them are business applications. Companies work with you know, we live in a era called information revolution after all. Some GUI toolkits are geared towards developing business large amount of data and they naturally need software for that. Well, applications. For example the WinForms or the Swing. They provide widgets that are adapted to the business application developing. A security or robustness. But definitelly not the look and feel. data grid widget is a good example. Swing toolkit has prorities like Database is a structured collection of data that is stored in a computer. A computer program, that manages and queries a database is calles a Database Management System (DBMS). Some thirty years ago, DBMS were available only in the research laboratories of giant companies like IBM. Later on, they began to DBMS everywhere. On the web, on our personal computers, in spread. But they were very expensive. These days, we can found various mobile devices or portables. We can have many different in the past. We live in interesting times. databeses for little or no money that would cost thousands of dollars There are various database models. The most significant database model is the relational database model (RDBMS). The data is divided into tables. Among these tables we define relations. We all have heard about various database management systems. There are several well known commercial DBMS as well as open source ones. Commercial RDBMS Oracle Sybase MS SQL Access Opensource RDBMS MySQL PostgreSQL Firebird SQLite Python programming language has modules for all above RDBMS. 1 de 12 27/04/2008 1:06 Working with databases http://www.zetcode.com/wxpython/databases/ SQLite Starting from Python 2.5.x series, an SQLite library is included in the python language. SQLite is a small embeddable library. This means No server is needed to work with SQLite. Therefore SQLite is also called a zero-configuration SQL database engine. SQLite has the following features. works with transactions that programmers can integrate the libraty inside their applications. no administration needed simple to use and fast small code footprint, less than 250 KB single file database structure supports databases up to 2 tebibytes (241 bytes) in size SQLite supports these data types: TEXT INTEGER FLOAT BLOB NULL Before we start working with SQLite, we define some important database. A query is written in SQL language. Structured Query terms. A database query is a search for information from a Language (SQL) is a computer language used to create, retrieve, IBM corporation. SQL language has three subsets. DML DDL DCL update and delete data from the database. It was developed by the The DML (Data Manipulation Language) is used to add, update and delete data. SQLite understands insert, update and delete sql commands. The DDL (Data Definition Language) is used to define from this group. The DCL (Data Control Language) is used to set privileges for database users. SQLite does not have this subset. query. A transaction is a unit of operation with a database management system. It can contain one or more queries. new tables and records. SQLite has create, drop, alter sql commands A cursor is a database object used to traverse the results of a SQL Transactions are used to ensure the integrity od data in a database. If everything is ok, transactions are commited. If one or more queries fails, transactions are rolled back. Databases that support 2 de 12 27/04/2008 1:06 Working with databases http://www.zetcode.com/wxpython/databases/ transactions are called transactional databases. An SQLite database metadata about the query from a database. It is a set of records that results from running a query. A single unit of structured data within a database table is called a record or a row. sqlite3 SQLite library includes a small command line utility called sqlite3. It is used to manually enter and execute SQL commands against a SQLite database. To launch this utility, we type sqlite3 into the shell. does not exist, a new one is created. We work with sqlite3 with a is a transactional database. An SQL result set is a set of rows and The command is to be followed by a database name. If the database definite set of dot commands. To show all available commands, we type .help. Some of the commands are shown in the following table. Command Description .databases .dump table .exit .headers ON|OFF .help .mode mode table .quit .read filename .show .tables pattern .width num num ... show a database name dump a table into an SQL text format exit the sqlite3 program show or hide column headers show help change mode for a table same as .exit execute SQL commands in a filename show sqlite3 settings list tables that match pattern set width for columns First, we create a new database called people. $ sqlite3 people SQLite version 3.3.13 Enter ".help" for instructions sqlite> sqlite> .databases seq name file --- --------------- ---------------------------------------------------------0 main /home/vronskij/tmp/people sqlite> .exit $ All commands of sqlite3 start with the dot "." character. To show all shows our current database. The .exit command quits the sqlite3 utility and returns to the shell. Next we create a table. available commands, we simply type .help. The .databases command 3 de 12 27/04/2008 1:06 Working with databases http://www.zetcode.com/wxpython/databases/ sqlite> .tables sqlite> create table neighbours(name text, age numeric, remark text); sqlite> .tables neighbours The .tables command shows all available tables in the database. We create a table called neighbours. Our table will have three columns. We will use text and numeric data types. Notice that each SQL command is followed by a semicolon ";". Now it is time to insert some real data. sqlite> sqlite> sqlite> sqlite> sqlite> sqlite> sqlite> sqlite> insert insert insert insert insert insert insert insert into into into into into into into into neighbours neighbours neighbours neighbours neighbours neighbours neighbours neighbours values('sandy', 7, 'stubborn'); values('jane', 18, 'beautiful'); values('mark', 28, 'lazy'); values('steven', 34, 'friendly'); values('alice', 17, 'slick'); values('tom', 25, 'clever'); values('jack', 89, 'wise'); values('lucy', 18, 'cute'); The SQL select command is probably the most widely used DML (data manipulation language) command. sqlite> select * from neighbours; sandy|7|stubborn jane|18|beautiful mark|28|lazy steven|34|friendly alice|17|slick tom|25|clever jack|89|wise lucy|18|cute The sqlite3 has several modes to display data. Namely: Mode Description csv column html insert line list tabs comma separated values left aligned columns html table code SQL insert statements for table one value per line values delimited by .separator string tab separated values The default mode is the list mode. We can see the current settings if we type the .show command. 4 de 12 27/04/2008 1:06 dump neighbours BEGIN TRANSACTION.dump. INSERT INTO "neighbours" VALUES('tom'. INSERT INTO "neighbours" VALUES('mark'.34.show echo: off explain: off headers: off mode: list nullvalue: "" output: stdout separator: "|" width: I prefer the column mode. age numeric. The default value is ten characters.zetcode. INSERT INTO "neighbours" VALUES('steven'. sqlite> .17. CREATE TABLE neighbours(name text.tables neighbours sqlite> .'cute').Working with databases http://www. sqlite> .dump command transforms the table into a set of SQL text 5 de 12 27/04/2008 1:06 .18.7.25. INSERT INTO "neighbours" VALUES('jane'.'slick').89. name age remark ---------. In the next step we change the default settings a bit. Finally we change the width of each column with the .headers on sqlite> . The . INSERT INTO "neighbours" VALUES('alice'. COMMIT.'stubborn'). INSERT INTO "neighbours" VALUES('sandy'.28.---. We utilize command .'friendly').'beautiful'). INSERT INTO "neighbours" VALUES('jack'.--------------sandy 7 stubborn jane 18 beautiful mark 28 lazy steven 34 friendly alice 17 slick tom 25 clever jack 89 wise lucy 18 cute We change the mode with the . Backing up the data is the most important thing.width 10 4 15 sqlite> select * from neighbours.'clever').18. sqlite3 has a simple solution.'wise'). INSERT INTO "neighbours" VALUES('lucy'.mode command to the column mode.com/wxpython/databases/ sqlite> .width command.headers command. We set headers on with the .mode column sqlite> .'lazy'). remark text). Working with databases http://www.com/wxpython/databases/ format./neighbours. name age remark ---------. The command . The pysqlite module is included under the package name sqlite3.sql sqlite> .connect(':memory:') 6 de 12 27/04/2008 1:06 . state.sql In the next steps we drop a table and recreate it from our file. import sqlite3 as lite con = lite. From python2.read . sqlite> drop table neighbours. SQLite python API pysqlite is a python interface to the SQLite library.tables neighbours sqlite> select * from neighbours. These SQL commands will recreate the table into the original text file.read we verify our data. Finally.5x series. command to execute all SQL commands in the specified file. it is included in the python language..zetcode.---------.connect('databasename') con = lite. We copy and paste these SQL commnads into a neighbours.tables sqlite> .tables shows no table.---------sandy 7 stubborn jane 18 beautiful mark 28 lazy steven 34 friendly alice 17 slick tom 25 clever jack 89 wise lucy 18 cute We drop the neighbours table with the drop table SQL command. we call the connect() module method. import sqlite3 as lite Simple steps create connection object create cursor object execute query fetch data (optional) close cursor and connection objects To create a connection. sqlite> . Then we type sqlite . Then we connect to our people database.).connect('people') >>> cur = con.) >>> cur. According to the documentation.close() >>> con. We will demonstrate this in short >>> cur. The fetchall() method retrieves all data the cursor and the connection object. We will test our examples there. commits automatically the changes. "copyright".cursor() >>> cur.). The database file is in our current directory. executes SQL commands. 22:02:36) [GCC 4. The execute() method that we have selected.). $ python Python 2. >>> >>> import sqlite3 as lite >>> con = lite. The kosher way to end our work is to close SQLite library works with transactions.close() >>> con. >>> cur. "credits" or "license" for more information. (u'jack'. (u'alice'. It is important to understand how it works.com/wxpython/databases/ There are two ways for creating a connection object.fetchall() [(u'sandy'.execute("select age from neighbours where name='lucy'") >>> print cur. 18 7 de 12 27/04/2008 1:06 .execute('select name from neighbours') >>> print cur.1. (u'tom'. SQLite library examples. We can create a connection to a database on the filesystem.).). Apr 6 2007. SQLite opens up a transaction.1c1 (release25-maint. for every DML statement.fetchone() (29. path to the filename. Commiting changes After that we call two cursor object methods. We simply specify the is done with a special string ':memory:'. We must commit our changes to apply them. To create a cursor object.).zetcode. (u'jane'. For every DCL statement. (u'steven'. This We launch a python interpreter.5.execute("update neighbours set age=29 where name='lucy'") >>> cur.Working with databases http://www.1. (u'mark'.2 (Ubuntu 4.close() >>> (CTRL + D) $ sqlite3 people sqlite> select age from neighbours where name='lucy'.).close() First we import the sqlite3 module.2-0ubuntu4)] on linux2 Type "help". we call the cursor() method of the connection object. We can also create a database in memory. When we executed the select statement using the python sqlite api. which >>> cur.connect('people'.execute("insert into neighbours values ('rebecca'. 16.commit() >>> cur. The data was not changed. The changes were not really written to the database.close() >>> con.close() >>> (CTRL + D) $ sqlite3 people sqlite> select age from neighbours where name='lucy'.cursor() >>> cur. We can create a connection. committed automatically. we set the isolation_level parameter to None.close() >>> (CTRL + D) $ sqlite3 people sqlite> .close() >>> con. we received result within a transaction context. which will automatically commit all our changes. In the next example we demonstrate that the DCL statements are is a part of the DCL language. 'shy')") >>> cur.com/wxpython/databases/ What went wrong? We did not commit our changes.execute("update neighbours set age=29 where name='lucy'") >>> con.tables neighbours relatives There is one more thing to mention. age numeric)') >>> cur. the data changes are really written to the database. >>> cur. rebecca|16|shy sqlite> Autoincrement Autoincremental primary key is a handy feature.execute('create table relatives(name text.zetcode. We insert new rows 8 de 12 27/04/2008 1:06 . We will use create table command. When we checked the data in the sqlite3 utility.Working with databases http://www. when >>> import sqlite3 as lite >>> con = lite. isolation_level=None) >>> cur = con. we got age 18.close() >>> con. This is done.close() >>> (CTRL + D) $ sqlite3 people sqlite> select * from neighbours where name='rebecca'. 29 After committing our changes with the commit() method of the connection object. paramstyle qmark The python Database API specification lists these possible parameter style passings: qmark numeric named format pyformat Python SQLite API uses the qmark (question mark) quoting.execute("insert into books(name. author) values ('%s'. name text. author) values ('father goriot'. '%s')" % (bookname. 'honore de balzac'). author) values ('anna karenina'. 'leo tolstoy').Working with databases and the key is incremented automatically by one. >>> import sqlite3 as lite >>> print lite. sqlite> select * from books.zetcode.com/wxpython/databases/ implementation of the autoincrement feature may differ among database. RDMSs. Security considerations It is possible but insecure to pass parameters this way.execute('insert into books(name. sqlite> insert into books (name. 1|anna karenina|leo tolstoy 2|father goriot|honore de balzac sqlite> The keyword autoincrement is used to create autoincremental primary key in SQLite. (bookname. Don't do this. These attacks are called SQL injections. In the next example we will show how it is done in SQLite sqlite> create table books(id integer primary key autoincrement not null. ?)'. author) values (?. bookauthor)) TODO blob 9 de 12 27/04/2008 1:06 . The previous example rewritten in qmark style: bookname = 'atlante illustrato di filosofia' bookauthor = 'ubaldo nicola' cur. The http://www. au sqlite> insert into books (name. bookauth It is vulnerable to attacks. bookname = 'atlante illustrato di filosofia' bookauthor = 'ubaldo nicola' cur. Bind(wx. 'Cancel'. 'Insert'. wx. 1.TextCtrl(panel. 9. 10)]) vbox.tc1 = wx.BoxSizer(wx.Panel(self. size=(150. (age).BoxSizer(wx. 1. title. databases and simple functional script. self. The next simple script will do only one specific thing.BOTTOM. 10). self.sp. -1. 'Name') remark = wx. wx.LEFT. 10). 10) self.tc1.SpinCtrl(panel.OnCancel. -1)) self. -1.tc2 = wx.ALIGN_CENTER | wx. id=insert. neigbours table. -1.GetId()) panel. size=(280. -1)) gs. parent. Now it is time to put it all together with wxPython in a #!/usr/bin/python # insertdata. 30)) insert = wx. ''. We will use our people database.ALL. 0. 5) vbox.StaticText(panel. id=cancel.StaticText(panel. -1.LEFT. wx. 0.connect('people') cur = con. 'Remark') age = wx.Add(hbox. parent.GetId()) self.Show(True) def OnInsert(self. 0. -1.LEFT.HORIZONTAL) name = wx. size=(-1.StaticText(panel.Add(gs.SetSizer(vbox) self.Add((-1. -1).sp = wx.LEFT. Insert data into a table.Add(insert) hbox. 0.zetcode. wx. -1. 9) vbox = wx. event): try: con = lite.cursor() 10 de 12 27/04/2008 1:06 .TextCtrl(panel.Frame. 'Age') self.__init__(self.Working with databases http://www. 2.VERTICAL) hbox = wx. size=(-1.Button(panel.AddMany([(name). id. size=(60. SQL language. (self.Bind(wx.FlexGridSizer(3.py import wx import sqlite3 as lite class InsertData(wx. 200)) panel = wx.Frame): def __init__(self. min=1. (self.EVT_BUTTON. (remark). 30)) cancel = wx. id.Button(panel.Add(cancel. title): wx. -1.com/wxpython/databases/ Putting it together So far we have been looking at the SQLite3 library. 10) vbox. (self.tc2. 30)) hbox. max=125) self. wx. -1) gs = wx.Centre() self. -1.OnInsert. wx. size=(150.EVT_BUTTON. GetValue() cur.sp.MainLoop() gs = wx. 9) In our Dialog box we use items of different size. remark)) con. age.tc2.com/wxpython/databases/ name = self.close() except lite. 'Error occured') dlg. 9.execute('insert into neighbours values(?.tc1.FlexGridSizer.GetValue() age = self.GetValue() cur.GetValue() remark = self. -1. ?.tc2. 11 de 12 27/04/2008 1:06 . ?)'.catch errors.FlexGridSizer(3. This is because working with data and databases is prone to implemented in SQLite library. str(error). ?)'. str(error). (name. except lite. 2. we get the values that the user has inserted. error: dlg = wx.Close() app = wx.App() InsertData(None.ShowModal() We have placed our database related code between the try .ShowModal() def OnCancel(self.Working with databases http://www.Error. event): self.commit() cur. remark)) This is the crutial part of the code.sp. These values are inserted into the database with the appropriate the SQL code.tc1.close() con.GridSizer have always the name = self. Items in wx.MessageDialog(self.zetcode. 'Error occured') dlg.execute('insert into neighbours values(?.MessageDialog(self.Error. error: dlg = wx. age. In the first three lines. ?.GetValue() remark = self. chosen the wx. The Error exception is a base class for all other exceptions clause.GetValue() age = self. (name. That's why we have same size. 'Insert Dialog') app. zetcode. Linux. 2007 © 2007 Jan Bodnar 12 de 12 27/04/2008 1:06 .Working with databases http://www. Sybase database tools Download Now! Windows.com/wxpython/databases/ Figure: insertdata.py dialog TODO: Supported Errors. Reports Home ‡ Contents ‡ Top of Page ZetCode last modified August 18. Warning Sybase SQL Tools Sybase SQL. OSX SQL Database Comparison Compare both Structure and Data Command Line Interface. The same happens. how several well known GUI interfaces could be done in wxPython. I always wondered how this File Manager File Hunter is a skeleton of a file manager. Our scripts will work out the interface but will not implement the functionality. we will create some application skeletons. and more Take international restaurant Test Flight Today! Costa del Coding Tools wxPythonSol Wedding? Pasta Fresca en Activex control Boqueria Application skeletons in wxPython In this section. It copies the lookout of the Krusader. Free usage of a widget. If you double click on the splitter widget. And I think. The goal is to show. When I was a beginner. Most manuals. the best file manager available on Unix systems. many newbies think the same.py 1 de 11 27/04/2008 1:07 . it will divide the File Hunter into two parts with the same width. En el mercado de Barcelona para hacer en Fully featured Explorer shell controls. Editor.Application skeletons in wxPython http://www. Browser. tutorials and books show only the basic or this could be done. if you resize the main window. Figure: Filemanager.com/wxpython/skeletons/ Home Contents wedding venue luxurious a Ideal beachside Debugger.zetcode. SetItemImage(j.ImageList(16.SetItemImage(j. '.SetStringItem(j.isdir(i): self.png'.InsertStringItem(j. ex) self.LIST_FORMAT_RIGHT) 'Modified') 220) 70) 100) 420) self. 'images/source_py. wx. 'images/pdf.SetItemImage(j. style=wx. time. id): wx.SetItemImage(j. name) self. self. wx.InsertStringItem(0.com/wxpython/skeletons/ #!/usr/bin/python import wx import os import time ID_BUTTON=100 ID_EXIT=200 ID_SPLITTER=300 class MyListCtrl(wx.path.ListCtrl. id. self.png'.listdir('. 3.InsertColumn(1. 1) 2) 3) 4) 0) if (j % 2) == 0: self.SetColumnWidth(2. self.Bitmap(i)) self. 'images/folder.il = wx.path.SetColumnWidth(3.splitext(i) ex = ext[1:] size = os. elif ex == 'py': self. else: self. elif ex == 'jpg': self.ListCtrl): def __init__(self.SetColumnWidth(1. 2.strftime('%Y-%m-%d %H:%M'.il.zetcode. str(size) + ' B') self. 'images/image.') self. time.InsertColumn(2.SetItemImage(j. 1. self.getsize(i) sec = os.localtime(sec))) if os. self. self.LC_REPORT) files = os. '#e6f1f5') 2 de 11 27/04/2008 1:07 .SetColumnWidth(0. 5) for i in files: (name.png'.InsertColumn(0. parent.') images = ['images/empty. parent.SetStringItem(j. 'Name') 'Ext') 'Size'.. 'images/up16.__init__(self.Add(wx.png'] self.InsertColumn(3.Application skeletons in wxPython http://www.png'. self.SetItemImage(0. 16) for i in images: self. elif ex == 'pdf': self.il.SetImageList(self.path. ext) = os.getmtime(i) self.SetStringItem(j.path.png'.SetItemBackgroundColour(j.IMAGE_LIST_SMALL) j = 1 self. Button(self. parent.OnExit. title): wx.AddSimpleTool(50.sizer2. "F8 Delete") ID_BUTTON + 7. 'Editor') tb. -1) p2 = MyListCtrl(self. "F9 Rename") ID_EXIT.AddSimpleTool(10. "F3 View") ID_BUTTON + 2. wx.HORIZONTAL) button1 button2 button3 button4 button5 button6 button7 button8 = = = = = = = = wx. "&Help") self.OnSize) self. wx. "&Edit") menuBar. "F10 Quit") wx. 1. 3 de 11 27/04/2008 1:07 . "&Show") menuBar. wx.AddSimpleTool(30.Application skeletons in wxPython http://www.Append(netmenu.SplitVertically(p1. wx.Bitmap('images/up. 'Terminal') tb.Bitmap('images/home. wx. id=ID_EXIT) tb = self.Append(helpmenu.Bitmap('images/refresh.zetcode.Menu() netmenu = wx.Realize() self. self.Add(button2. "&Config") menuBar.Bitmap('images/write. -1) self.Add(button4. style=wx. self.AddSimpleTool(60.Menu() helpmenu = wx. p2) self."E&xit". ID_SPLITTER. wx.png').Button(self.AddSimpleTool(20.EXPAND) wx.splitter = wx.AddSimpleTool(70.Append(editmenu.OnDoubleClick.Add(button3.splitter.sizer2.Menu() showmenu = wx. 'Previous') tb.AddSeparator() tb.Bitmap('images/terminal.splitter.TB_FLAT | wx. wx.TB_TEXT) tb.Append(ID_EXIT.EVT_SIZE.png'). self.EVT_SPLITTER_DCLICK.Append(filemenu. 1. id=ID_SPLITTER) filemenu= wx.__init__(self.Bitmap('images/help. parent.Append(showmenu.EXPAND) self. wx. self.png').Frame. -1.Button(self."&File") menuBar.EXPAND) wx.Menu() menuBar = wx. id.Button(self.Add(button1. 1.splitter.png'). 'Home') tb.EXPAND) wx. self.Bind(wx. "F4 Edit") ID_BUTTON + 3.png').MenuBar() menuBar. "&Net") menuBar.EVT_MENU.NO_BORDER | wx.SP_BORDER) self.AddSimpleTool(40.sizer2.splitter.SetMinimumPaneSize(50) p1 = MyListCtrl(self.EXPAND) wx.Menu() filemenu.Menu() configmenu = wx. wx.Button(self.Add(button5. wx. wx.png').Append(configmenu.com/wxpython/skeletons/ j = j + 1 class FileHunter(wx. ID_BUTTON + 1.sizer2. "F7 Mkdir") ID_BUTTON + 6. 'Refresh') tb. wx.png'). wx. self. 1.sizer2.Frame): def __init__(self. "F6 Move") ID_BUTTON + 5. 'Help') tb. 1.Bind(wx.Button(self.Button(self.Button(self.SetMenuBar(menuBar) self.Bitmap('images/previous.Bind(wx.BoxSizer(wx.AddSeparator() tb.sizer2 = wx.CreateToolBar( wx. self." Terminate the program") editmenu = wx.SplitterWindow(self. 'Up one directory') tb. "F5 Copy") ID_BUTTON + 4. wx. title) self.TB_HORIZONTAL | wx. Application skeletons in wxPython http://www.zetcode.com/wxpython/skeletons/ self.sizer2.Add(button6, 1, wx.EXPAND) self.sizer2.Add(button7, 1, wx.EXPAND) self.sizer2.Add(button8, 1, wx.EXPAND) self.Bind(wx.EVT_BUTTON, self.OnExit, id=ID_EXIT) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.splitter,1,wx.EXPAND) self.sizer.Add(self.sizer2,0,wx.EXPAND) self.SetSizer(self.sizer) size = wx.DisplaySize() self.SetSize(size) self.sb = self.CreateStatusBar() self.sb.SetStatusText(os.getcwd()) self.Center() self.Show(True) def OnExit(self,e): self.Close(True) def OnSize(self, event): size = self.GetSize() self.splitter.SetSashPosition(size.x / 2) self.sb.SetStatusText(os.getcwd()) event.Skip() def OnDoubleClick(self, event): size = self.GetSize() self.splitter.SetSashPosition(size.x / 2) app = wx.App(0) FileHunter(None, -1, 'File Hunter') app.MainLoop() SpreadSheet Gnumeric, KSpread and OpenOffice Calc are famous spreadsheet of a spreadsheet application in wxPython. applications available on Unix. The following example shows a skeleton Applications have their own life. This is also true for educational scripts. After uprading to wx.Python 2.8.1.1 I realized, that the spreadsheet example does not work. The following line was the problem. toolbar2.AddControl(wx.StaticText(toolbar2, -1, ' ')) Of course, we cannot add a widget to itself. But the previous version of signalizing a problem. It might or might not work on the Mac and the toolkit was happy with it. Under the current version it did not work, Windows. Originally, I wanted to add some space between the combo I dropped the line. boxes. Under the new version of the toolkit it stopped to work either so 4 de 11 27/04/2008 1:07 Application skeletons in wxPython http://www.zetcode.com/wxpython/skeletons/ Besides fixing this bug, I also cleaned the code a bit and replaced the ones (AddLabelTool()). depreciated methods (AddSimpleTool()) of the toolbar with the new Figure: Spreadsheet #!/usr/bin/python # spreadsheet.py from wx.lib import sheet import wx class MySheet(sheet.CSheet): def __init__(self, parent): sheet.CSheet.__init__(self, parent) self.row = self.col = 0 self.SetNumberRows(55) self.SetNumberCols(25) for i in range(55): self.SetRowSize(i, 20) def OnGridSelectCell(self, event): self.row, self.col = event.GetRow(), event.GetCol() 5 de 11 27/04/2008 1:07 Application skeletons in wxPython http://www.zetcode.com/wxpython/skeletons/ control = self.GetParent().GetParent().position value = self.GetColLabelValue(self.col) + self.GetRowLabelValue(self.row) control.SetValue(value) event.Skip() class Newt(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, -1, title, size = (550, 500)) fonts = ['Times New Roman', 'Times', 'Courier', 'Courier New', 'Helvetica', 'Sans', 'verdana', 'utkal', 'aakar', 'Arial'] font_sizes = ['10', '11', '12', '14', '16'] box = wx.BoxSizer(wx.VERTICAL) menuBar = wx.MenuBar() menu1 = wx.Menu() menuBar.Append(menu1, menu2 = wx.Menu() menuBar.Append(menu2, menu3 = wx.Menu() menuBar.Append(menu3, menu4 = wx.Menu() menuBar.Append(menu4, menu5 = wx.Menu() menuBar.Append(menu5, menu6 = wx.Menu() menuBar.Append(menu6, menu7 = wx.Menu() menuBar.Append(menu7, menu8 = wx.Menu() menuBar.Append(menu8, '&File') '&Edit') '&Edit') '&Insert') 'F&ormat') '&Tools') '&Data') '&Help') self.SetMenuBar(menuBar) toolbar1 = wx.ToolBar(self, -1, style= wx.TB_HORIZONTAL) toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_new.png')) toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_open.png')) toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_save.png')) toolbar1.AddSeparator() toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_cut.png')) toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_copy.png')) toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_paste.png')) toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_delete.png')) toolbar1.AddSeparator() toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_undo.png')) toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_redo.png')) toolbar1.AddSeparator() toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/incr22.png')) toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/decr22.png')) toolbar1.AddSeparator() toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/chart.xpm')) toolbar1.AddSeparator() toolbar1.AddLabelTool(-1, '', wx.Bitmap('icons/stock_exit.png')) toolbar1.Realize() toolbar2 = wx.ToolBar(self, wx.TB_HORIZONTAL | wx.TB_TEXT) self.position = wx.TextCtrl(toolbar2) font = wx.ComboBox(toolbar2, -1, value = 'Times', choices=fonts, size=(100, -1), style=wx.CB_DROPDOWN) font_height = wx.ComboBox(toolbar2, -1, value = '10', choices=font_sizes, size=(50, -1), style=wx.CB_DROPDOWN) 6 de 11 27/04/2008 1:07 Application skeletons in wxPython http://www.zetcode.com/wxpython/skeletons/ toolbar2.AddControl(self.position) toolbar2.AddControl(font) toolbar2.AddControl(font_height) toolbar2.AddSeparator() bold = wx.Bitmap('icons/stock_text_bold.png') toolbar2.AddCheckTool(-1, bold) italic = wx.Bitmap('icons/stock_text_italic.png') toolbar2.AddCheckTool(-1, italic) under = wx.Bitmap('icons/stock_text_underline.png') toolbar2.AddCheckTool(-1, under) toolbar2.AddSeparator() toolbar2.AddLabelTool(-1, '', wx.Bitmap('icons/text_align_left.png')) toolbar2.AddLabelTool(-1, '', wx.Bitmap('icons/text_align_center.png')) toolbar2.AddLabelTool(-1, '', wx.Bitmap('icons/text_align_right.png')) box.Add(toolbar1, border=5) box.Add((5,5) , 0) box.Add(toolbar2) box.Add((5,10) , 0) toolbar2.Realize() self.SetSizer(box) notebook = wx.Notebook(self, -1, style=wx.RIGHT) sheet1 = MySheet(notebook) sheet2 = MySheet(notebook) sheet3 = MySheet(notebook) sheet1.SetFocus() notebook.AddPage(sheet1, 'Sheet1') notebook.AddPage(sheet2, 'Sheet2') notebook.AddPage(sheet3, 'Sheet3') box.Add(notebook, 1, wx.EXPAND) self.CreateStatusBar() self.Centre() self.Show(True) app = wx.App() Newt(None, -1, 'SpreadSheet') app.MainLoop() Much of the code builds the menus and toolbars. Besides, it is quite a simple example. class MySheet(sheet.CSheet): def __init__(self, parent): sheet.CSheet.__init__(self, parent) self.row = self.col = 0 self.SetNumberRows(55) self.SetNumberCols(25) for i in range(55): self.SetRowSize(i, 20) The MySheet class inherits from the CSheet class, which is located in 7 de 11 27/04/2008 1:07 Application skeletons in wxPython http://www.zetcode.com/wxpython/skeletons/ thel wx.lib module. It is basically a wx.Grid widget with some additional functionality. We set the row size to 20px. This is purely for aesthetical purpose. control = self.GetParent().GetParent().position The position text control shows the selected cell of the grid widget. It is the first widget of the second toolbar. Being inside a MySheet class, we class. MySheet is a child of the notebook. And notebook is a child of GetParent() method twice. need to get a reference to the text control, which is defined in the Newt Newt. So we manage to get to the position text control by calling the notebook = wx.Notebook(self, -1, style=wx.RIGHT) This is a bug. Under current version of wxPython (on GTK+), right is bottom and bottom is right. Browser These days internet browsers are one of the most important Firefox. We mimic the look of a Firefox in our script. applications in the IT world. The best available browsers are Opera and Figure: Browser.py #!/usr/bin/python 8 de 11 27/04/2008 1:07 parent. title.Add(toolbar1. '&File') menubar.Bitmap('icons/stop. -1.Panel(self.Add(address.png'). 40)) back = wx. -1. wx.Panel(panel.TOP.BoxSizer(wx. wx.LEFT.png').Add(go.BoxSizer(wx. '') edit = wx.Bitmap('icons/home.Frame): def __init__(self. wx. style=wx.Append(view.Menu() menubar. wx.BitmapButton(toolbar1.zetcode. style=wx.__init__(self. -1)) hbox1.Application skeletons in wxPython http://www.png').lib. 1.Menu() bookmarks = wx.Append(file. size=(50.Panel(panel. wx. '&Go') menubar.Bitmap('icons/go.Menu() go = wx.png'). '&Help') self.SetBackgroundColour('WHITE') menubar = wx. -1.TOP | wx.Add(line. id.BitmapButton(toolbar1.Frame. '&Bookmarks') menubar.BitmapButton(toolbar1. 400)) panel = wx.SetMenuBar(menubar) vbox = wx. -1. 4) vbox. wx.VERTICAL) hbox1 = wx. style=wx. style=wx. -1.Add(back) hbox1. -1)) go = wx. 4) hbox1.NO_BORDER) text = wx. 0. 0.TextCtrl(toolbar1. wx. size=(450. -1.Append(bookmarks.Bitmap('icons/forward.BitmapButton(toolbar1. id.png').Add(refresh) hbox1.png'). -1. '&Quit'. -1) panel.NO_BORDER) stop = wx.BitmapButton(toolbar1. '&Edit') menubar. -1.EXPAND) line = wx.Bitmap('icons/back.Bitmap('icons/refresh.NO_BORDER) home = wx.Append(edit. parent.buttons import GenBitmapTextButton class Browser(wx.Bitmap('icons/love.BitmapButton(toolbar2.NO_BORDER) address = wx.Add(home) hbox1. -1.MenuBar() file = wx.StaticLine(panel) vbox. 0. 0. 30)) bookmark1 = wx. -1.EXPAND) toolbar2 = wx.com/wxpython/skeletons/ import wx from wx.Menu() file.Menu() help = wx.HORIZONTAL) toolbar1 = wx. style=wx.Add(forward) hbox1.ComboBox(toolbar1.NO_BORDER) forward = wx. wx. size=(-1.Append(help. style=wx.Add(text.RIGHT. '&Tools') menubar. size=(150. -1. 4) hbox1.Add(stop) hbox1. wx.Menu() tools = wx. wx. '&View') menubar.png'). wx.Append(go.Append(1.NO_BORDER) refresh = wx.BitmapButton(toolbar1.HORIZONTAL) hbox2 = wx.BoxSizer(wx.TOP | wx.Menu() view = wx. title): wx. wx.Append(tools. size=(-1.NO_BORDER) 9 de 11 27/04/2008 1:07 . style=wx. hbox1... wx. This was necessary to make it resizable.Panel(panel. style=wx.SetSizer(hbox2) vbox.BoxSizer(wx. size=(-1.App(0) Browser(None.Add(forward) hbox1. usually called an address bar.png').png'). This kind of combo box is the proportion set to 1. hbox1 = wx.Add(refresh) We create a horizontal sizer and add all necessary buttons. hbox1. it was some kind of a panel border. for which we don't have a 10 de 11 27/04/2008 1:07 . toolbar1 = wx.StaticLine(panel) vbox. 0. flag=wx. First I thought. flag=wx. that has The second toolbar was created in a similar way.BitmapButton(toolbar2.HORIZONTAL) . It is not possible Dunn.Add(address. wx. -1. 4) Then we add the combo box to the sizer.EXPAND) panel. wx. 40)) The trick is simple.Bitmap('icons/books. line = wx.CreateStatusBar() self.Show(True) app = wx. 0. style=wx.Add(bookmark2. The toolbars are I tested all possible borders.TOP. wx.RIGHT. border=5) hbox2.Add(back) hbox1.Centre() self. border=5) hbox2. So we must do a workaround.Toolbar. how to create a sizeable combo box.Application skeletons in wxPython http://www. -1.Bitmap('icons/sound. -1. we must create a solution. -1.Add(bookmark1.Add(toolbar2.Panel. It is a simple static line! Sometimes. that it is the only widget. separated by a line.com/wxpython/skeletons/ bookmark2 = wx.NO_BORDER) hbox2. Confirmed with Robin both Firefox and Opera? We cannot use a wx.Add(bookmark3) toolbar2. Notice.EXPAND) line = wx.NO_BORDER) bookmark3 = wx. but it wasn't quite what I expected. 'Browser') app. that is used in to create such a functionality with wx. 1.Toolbar. wx.zetcode.RIGHT.SetSizer(vbox) self.Add(line. We create a plain wx.StaticLine(panel) Then I suddently got it.BitmapButton(toolbar2.MainLoop() The question was. com for All Your Needs Alcaidesa Discount Golf Only 68€ until 31. Menu Find Printers of Customized Menus.com/wxpython/skeletons/ suitable widget. By using simple common sense. we can easily find a way.08 Lunch menu Home ‡ Contents ‡ Top of Page ZetCode last modified August 18.zetcode. 2007 © 2007 Jan Bodnar 11 de 11 27/04/2008 1:07 .Application skeletons in wxPython http://www. Use Business.05. The FLTK toolkit is a kind of a spartan toolkit.stattext. The hyperlink widget will be based on an existing wx. Toolkits usually provide only the most common widgets like buttons. text widgets. wxPython is a heavy weight one. But you couldn't find it. parent.url = URL 1 de 9 27/04/2008 1:07 . style=0. name='Link'. pos. Or Here I assume. size. label. name) self. that the programemer will create the more complicated ones himself. Easier Python Development Editor. Then you were looking at a list of widgets provided by your favourite gui library.py import wx from wx.g. how a particular gui item was created? Probably every wannabe programmer has. Spartan toolkits and heavy weight toolkits.__init__(self. It provides only the very basic widgets and assumes. a widget that measures the Programmers must create such widgets by themselves. widgets. For example a speed meter widget. you have read the chapter on the GDI. label=''. URL=''): GenStaticText. There are two he can create a custom widget from scratch. possibilities. Yet it does not provide the more specialized capacity of a CD to be burned (found e. Contents Debugger.stattext import GenStaticText import webbrowser class Link(GenStaticText): def __init__(self. style.Creating custom widgets http://www. in nero). They do it by using the drawing tools provided by the toolkit.lib. Browser. parent. No toolkit can provide all possible widgets. There are actually two kinds of toolkits.com/wxpython/customwidgets/ HomeFaster. size=(-1. Free Download! Creating custom widgets Have you ever looked at an application and wondered. sliders etc. and more Python IDE Free Floor Plan Software Make Floor Plans in Minutes See Examples. It has lots of widgets.zetcode. pos=(-1. Toolkits also don't have usually charts.GenStaticText widget.lib. A programmer can modify or enhance an existing widget. -1). id. -1). id=-1. #!/usr/bin/python # link. A hyperlink widget The first example will create a hyperlink. BOLD. pos=(10. -1. parent. widget and the webbrowser module.font2) self. wx.__init__(self. 60).font2) self.lib.font1 = wx. size=(220. 'Knowledge only matters'.Centre() self.OnMouseEvent) self. In this example we don't draw anything.Show(True) app = wx. We inherit from a base wx.font2) event.lib.SetFont(wx.SWISS. We will use it to open links in a default browser.Font(9. webbrowser module is a standard self.Bind(wx. wx. self. title): wx. -1.EVT_MOUSE_EVENTS.MainLoop() This hyperlink widget is based on an existing widget.SetForegroundColour('#0000ff') self.Font(9.StockCursor(wx.Bind(wx.App() HyperLink(None.stattext. -1. pos=(10.SetFont(self.BOLD.Frame): def __init__(self.Skip() class HyperLink(wx. 30)) motto. 'A Hyperlink') app.EVT_MOTION. parent.SetFont(self.OnMouseEvent) def OnMouseEvent(self. title. event): if event.CURSOR_HAND)) self. False.NORMAL.NullCursor) self. 150)) panel = wx. True. URL='http://www.com') motto = GenStaticText(panel. self.SetCursor(wx.Moving(): self. So we have a text 2 de 9 27/04/2008 1:07 .SWISS. 'ZetCode'. wx. wx.Creating custom widgets http://www.zetcode.SetFont(self.NORMAL.SetForegroundColour('#0000ff') The idea behind creating a hyperlink widget is simple.SetCursor(wx.GenStaticText widget class. 'Verdana') self.com/wxpython/customwidgets/ self. from wx.SWISS.url) else: self. which we modify a bit.stattext import GenStaticText import webbrowser Here we import the base widget from which we derive our hyperlink python module. wx.open_new(self.Frame. id.NORMAL.zetcode.LeftUp(): webbrowser. False.Font(9.font2 = wx. wx. 'Verdana') self. wx. wx. we just use an existing widget.font1) elif event.Panel(self. -1) Link(panel. id. wx. 'Verdana')) self.SetFont(self.BOLD. open_new(self. We change the font and the colour of the text. we open the link in a defaul browser. To avoid flicker.com/wxpython/customwidgets/ widget. we change the font to underlined and also change the mouse pointer to a hand cursor.url) If we left click on the link.StockCursor(wx. Hyperlinks are usually blue. We put a wx.py import wx 3 de 9 27/04/2008 1:07 .Moving(): self. that we create from a ground up.Panel on the bottom of the window and draw the entire widget kind of widget. you already saw this Remark for windows users.SetFont(self. if event.LeftUp(): webbrowser.font1) If we hover a mouse pointer over the link. If you have ever burned a cd or a dvd. Then we modify it a bit to make a hyperlink out of this text. elif event. Figure: A Hyperlink widget Burning widget This is an example of a widget.SetCursor(wx. manually.CURSOR_HAND)) self.zetcode. use double buffering.Creating custom widgets http://www. #!/usr/bin/python # burning. OnPaint) self. step): dc.Panel(panel. 75. 0. i-width/2. 750.Brush('#FFFFB8')) dc. i.OnSize) def OnPaint(self. event): num = range(75. height = dc.0) * self.SetBrush(wx. 30).GetParent().BoxSizer(wx. 200)) self.Panel(self. id): wx. parent. size=(-1.Font(9. 30) dc. id. till.Frame. (150. style=wx.cw >= 700: dc. (-1. 30) dc. 0.Creating custom widgets http://www.Bind(wx.0)) j = 0 till = (w / 750.com/wxpython/customwidgets/ class Widget(wx. -1) self.SetBrush(wx.parent = parent self.VERTICAL) hbox = wx. 30) else: dc.0) * 700 if self.cw step = int(round(w / 10. title. 8) j = j + 1 def OnSize(self.cw = self. 10*step. event): self. -1).Slider(CenterPanel.DrawRectangle(full. wx.SUNKEN_BORDER) self. self.Panel.font) w.BoxSizer(wx.Frame): def __init__(self. h = self.Pen('#5C5142')) for i in range(step.DrawRectangle(0.DrawRectangle(0.DrawLine(i.cw full = (w / 750. wx.BoxSizer(wx.__init__(self. parent. -1). id.HORIZONTAL) 4 de 9 27/04/2008 1:07 .PaintDC(self) dc.FONTSTYLE_NORMAL.Bind(wx. 0.Refresh() class Burning(wx. id.HORIZONTAL) hbox2 = wx. full.EVT_SIZE.GetSize() self. size=(330. title): wx. 75) dc = wx.SL_LABELS vbox = wx. parent. 6) width.Brush('#FFFFB8')) dc.__init__(self.EVT_PAINT. 0.SetPen(wx. wx.sld = wx.SetPen(wx.Pen('#FFFFB8')) dc. self.DrawText(str(num[j]). 700. 'Courier 10 Pitch') self.Panel): def __init__(self.SetPen(wx.SetFont(self.SetBrush(wx. -1.font = wx. False.Brush('#ffafaf')) dc.parent. wx. 0. parent.GetTextExtent(str(num[j])) dc.SetPen(wx.FONTWEIGHT_NORMAL. till-full.Pen('#ffafaf')) dc.cw = 75 panel = wx.Pen('#FFFFB8')) dc.zetcode.FONTFAMILY_DEFAULT. -1) CenterPanel = wx. 1.Centre() self. which divide the the capacity of the medium. 1. 'Burning widget') app.sld.com/wxpython/customwidgets/ self.Add(self.EXPAND) hbox3.Refresh() app = wx. we draw the numbers.0) * 700 We draw the widget dynamically.wid = Widget(panel.sld.Show(True) def OnScroll(self.TOP.parent.Add(hbox2. wx. We draw the yellow or red and yellow rectangle. which indicate 5 de 9 27/04/2008 1:07 . If we reach value 700. till = (w / 750.EXPAND) hbox2.wid.BoxSizer(wx.GetParent(). Notice the use of floating point arithmetics.SetFocus() self. 0.EXPAND) vbox.Add(self.Bind(wx. This value comes from determines the point. -1.GetSize() self.EVT_SCROLL.cw = self. Finally. That is why we must calculate the parameter determines the total size to be drawn.cw = self.Panel onto which we draw the custom widget. wx. And vice versa. we began drawing in red colour. the maximum is w. The minimum value of our custom widget is 0. h = self. the slider widget.0) * self. 35) CenterPanel.App() Burning(None.Add(hbox. where we begin to draw in red color. This is to achieve greater precision. 1.HORIZONTAL) self. event): self. class. wx..MainLoop() All the important code resides in the OnPaint() method of the Widget the free space available to us.EXPAND) http://www. wx. Then we draw the vertical lines..SetSizer(hbox3) vbox.OnScroll) panel. wx. This widget shows graphically the total capacity of a medium and widget.sld.wid. widget into several parts. The widget is controlled by a slider 750. The till the burning widget. 0.Creating custom widgets hbox3 = wx.Add(CenterPanel. This normally indicates overburning. -1) hbox. The full parameter The actual drawing consists of three steps. It is a proportion of the whole area. The greater the window. self.SetSizer(vbox) self.zetcode.cw full = (w / 750.cw .GetValue() self. the greater size of the wx. The temperature. To avoid flicker. when the burning widget Figure: Burning widget The CPU widget There are system applications that measure system resources. Specialized 6 de 9 27/04/2008 1:07 . we get the actual value and save it is drawn. Remark for windows users.GetValue() self.Refresh() If we scroll the thumb of the slider. By displaying a simple widgets are created to make the application more appealing. use double buffering. This value is used. into the self.Creating custom widgets http://www.com/wxpython/customwidgets/ def OnSize(self. Then we cause the widget to be redrawn. Change the size of the application and the width of the slider.sld. memory and CPU consuption etc.wid.cw = self. def OnScroll(self.Refresh() Every time the window is resized. event): self. The following widget is often used in system applications.cw parameter. we refresh the widget.zetcode. text like CPU 54% you probably won't impress your users. This causes the widget to repaint itself. event): self. DrawRectangle(10.EVT_PAINT.Brush('#075100')) dc. 0.HORIZONTAL) self. -1) self. parent.SL_INVERSE) self.LEFT | wx.TOP. 21): if i > rect: dc.SL_LABELS | wx.sel rect = pos / 5 for i in range(1. i*4. 0.Frame): def __init__(self. 5) dc. title.Creating custom widgets http://www. 30. self.Add(self.Slider(panel.PaintDC(self) dc.slider. size=(190.SetSizer(hbox) 7 de 9 27/04/2008 1:07 .parent = parent self. 30. -1). -1) centerPanel = wx. 23) self.GetParent().sel = 0 panel = wx. 100) dc. 5) class CPUWidget(wx.zetcode. i*4.DrawRectangle(41. self.SetDeviceOrigin(0.SetBrush(wx. size=(80. (-1. id.com/wxpython/customwidgets/ #!/usr/bin/python # cpu.Bind(wx. id. event): dc = wx.SetAxisOrientation(True.Panel): def __init__(self.OnPaint) def OnPaint(self. 5) dc. 140)) self.cpu = CPU(centerPanel. -1.Add(centerPanel.DrawRectangle(10. parent. parent.Brush('#36ff27')) dc.parent. parent.Panel(self.SetBackgroundColour('#000000') self.TOP. True) pos = self.Frame.__init__(self. title): wx. i*4. id.EVT_SCROLL. 5) else: dc.SetBrush(wx.LEFT | wx.VERTICAL | wx.slider.py import wx class CPU(wx. 0.GetParent().slider = wx. self. id): wx.__init__(self. 110)) self. -1) hbox = wx.Panel(panel. i*4.OnScroll) panel.Bind(wx. 30. (25. 20) hbox.SetFocus() hbox. 30. 90). wx.Panel.sel.BoxSizer(wx.DrawRectangle(41. wx. 100. wx. SetBrush(wx. event): self. 30. If the number of the it in a dark green color. convertion from slider values into rectangles. that will be drawn in bright for i in range(1. 5) else: dc.Brush('#075100')) dc. 'cpu') app. 5) dc.parent.sel = event.DrawRectangle(41.App() CPUWidget(None.DrawRectangle(10. 5) dc. The rect parameter makes a green color. i*4. 30.DrawRectangle(41. 20 in each column. This is to make the drawing intuitive. 21): if i > rect: dc.Creating custom widgets http://www. The color of the rectangles depend on the value of the slider. The color can be dark green or bright green. rectangle being drawn is greater than the converted rect value. The slider has 100 numbers. -1. We have 20 rectangles in each column. We create a black panel.MainLoop() Creating this widget is quite simple.Centre() self.SetAxisOrientation(True.cpu.com/wxpython/customwidgets/ self.sel rect = pos / 5 Here we get the value of the sizer. i*4. 100) dc.Show(True) def OnScroll(self. Otherwise in bright green. Then we draw small rectangles onto this panel.Brush('#36ff27')) dc.SetDeviceOrigin(0.DrawRectangle(10.Refresh() app = wx. 5) Here we draw 40 rectangles. 30. pos = self. True) Here we change the default coordinate system to cartesian.GetParent().zetcode.GetInt() self. 30.GetParent(). we draw 8 de 9 27/04/2008 1:07 . i*4. i*4. dc.SetBrush(wx. twotacos.com/wxpython/customwidgets/ Figure: cpu widget I Portletsuite WebCMS Like Widgets www.Creating custom widgets http://www. 2007 © 2007 Jan Bodnar 9 de 9 27/04/2008 1:07 .zetcode.2 Home ‡ Contents ‡ Top of Page ZetCode last modified June 3.com Over 40 out-of-the-box portlets Direct use in BEA Portal 9. We load resources #!/usr/bin/python # xml.com Python IDE Developing HL7 Solutions? HL7 Software Development Components and COM Services.0" ?> <resource> <object class="wxPanel" name="MyPanel"> 1 de 2 27/04/2008 1:08 . Contents www.wingware.xrc') res. parent. In thid file.__init__(self. <?xml version="1.Close() app = wx.Show(True) id=xrc.Frame): def __init__(self.MainLoop() This is resource file resource. title): wx. Several GUI builders use this concept for creating interfaces. Free Trial. title) res = xrc. parent.XmlResource('resource. we use tags like <object></object>. and Debug Free 30-day Trial Edit. In our example from a file.XRCID('CloseButton')) def OnClose(self.py we create a simple frame window with one button.Center() self. Figure: myconfig.xrc as xrc class Xml(wx. event): self. -1. 'xml. id. where we define our widgets and their patterns. 'MyPanel') self. For example the famous Glade.Frame.App() Xml(None.py import import wx wx.LoadPanel(self. self.xml resource files http://www. <item></item> etc.EVT_BUTTON. self. load a panel and bind an event to a button.Bind(wx.OnClose.py') app.zetcode.com/wxpython/xmlresource/ HomeTest.xrc It is a xml file. id. xml resource files The idea behind xml resources is to separate the interface from the code of an application. zetcode. Home ‡ Contents ‡ Top of Page ZetCode last modified June 3.xml resource files http://www.gives us the handlers of our widgets defined in resource file item Developing HL7 Solutions? HL7 Software Development Components and COM Services. Free Trial.gives us the id of a button or menu XRCCTRL(resource_name) .com/wxpython/xmlresource/ <object class="wxButton" name="CloseButton"> <label>Close</label> <pos>15.10</pos> </object> </object> </resource> We use these two calls for working with widgets: XRCID(resource_name) . Open XML Open XML provides an open platform for collaboration. 2007 © 2007 Jan Bodnar 2 de 2 27/04/2008 1:08 . Same piece of code can The wx. Be it a screen or a printer.com Free Floor Plan Software Make Floor Plans in Minutes See Examples. Test. To begin drawing graphics. Each derived class is intended to be used under specific conditions. printer or a file. and Debug Free 30-day Trial Home Contents www.DC.zetcode. In wxPython the device context is called wx.DC as a device context onto which which graphics and text can be drawn. The GDI consists of 2D Vector Graphics. we must create a device context (DC) object. The GDI insulates the programmer from the hardware. The documentation defines wx. Derived wx. It is used to interact with graphic The GDI (Graphics Device Interface) is an interface for devices such as monitor.DC is not intended to be used directly.The Graphics Device Interface http://www. Figure: The GDI structure From the programmer's point of view. Free Download! The GDI working with graphics. Instead a write to different kinds of devices.DC classes 1 de 44 27/04/2008 1:08 . Fonts and Images.com/wxpython/gdi/ Python IDE Edit. the GDI is a group of classes and methods for working with graphics. The GDI allows having to be concerned about the details of a particular programmers to display data on a screen or printer without device. It represents number of devices in a generic way.wingware. programmer should choose one of the derived classes. But there is one difference between the wx. title): 2 de 44 27/04/2008 1:08 . Excluding the second point.py import wx class Line(wx.PaintDC should not be used from a wx. int y1. parent.PostScriptDC is used be used only from a wx. The wx. The client area is the area of a window without it's decorations (title and border). to draw graphics on the bitmap. The wx. The wx. int y2) This method draws a line from the first point to the second.ClientDC is used to draw on the client area of a The wx.ClientDC shoud Drawing a simple line Our first example will draw a simple line onto the client area of a window.zetcode.PaintDC is used to draw on the client area as well. The wx.PaintDC and the wx. The wx. int x2. window (Windows only). DrawLine(int x1.PrinterDC is used to access a printer (Windows only). #!/usr/bin/python # line1. The wx.ScreenDC is used to draw anywhere on the screen.Frame): def __init__(self.PaintEvent.com/wxpython/gdi/ wxBufferedDC wxBufferedPaintDC wxPostScriptDC wxMemoryDC wxPrinterDC wxClientDC wxPaintDC wxScreenDC wxWindowDC The wx. This includes window decorations.ClientDC. id.WindowDC is used if we want to paint on the whole window.MemoryDC is used to write to PostScript files on any platform.PaintEvent.The Graphics Device Interface http://www. The wx. All our drawings would be therefore lost. 60.The Graphics Device Interface http://www. the line will disappear. 60) app = wx.Frame widget.FutureCall(2000. parent. if we cover it by another window and uncover afterwards.Show(True) def DrawLine(self): dc = wx. size=(250. 'Line') app. if it is resized. if it is maximized. We call the draws a line on our window. We have to draw the line each time the window is resized. 3 de 44 27/04/2008 1:08 .FutureCall(2000. This is the reason.DrawLine(50. self. is the window on which we want to draw. 190.__init__(self. It is also redrawn.DrawLine(50. 190. The window is drawn to it's default state and our line is lost. self. We will draw our line inside a method that will be hooked to the paint event. title.Centre() self. 150)) wx. In our case it is self. it is drawing after the window has been created.ClientDC device context. drawn. We do it because. The solution is the wx.PaintEvent.ClientDC(self) dc.MainLoop() wx. The window is also redrawn.App() Line(None. the window is redrawn.DrawLine) self.DrawLine) We call the DrawLine() method after the window has been created. If we resize the window. 60) We create a wx. Why is this happening? Every window is redrawn. -1. The following example shows how it is done. The only parameter which is a reference to our wx.Frame.com/wxpython/gdi/ wx. when the window is created.zetcode. DrawLine() method of the device context. 60.FutureCall() method. id.ClientDC(self) dc. why we call the wx. We can start def DrawLine(self): dc = wx. This call actually It is very important to understand the following behaviour. This event is triggered every time. title. that this time we have used the wx.EVT_PAINT. parent.EVT_PAINT.OnPaint) Here we bind the OnPaint method to the wx.PaintDC(self) dc.Bind(wx.PaintDC(self) Notice.DrawLine(50. if we resize our window (cover it. It means. self. id. dc = wx. 150)) self. id.The Graphics Device Interface http://www.py import wx class Line(wx.PaintEvent event.Frame): def __init__(self. -1.App() Line(None. Now the line will not disappear. we call the OnPaint method. self.Bind(wx.zetcode.Frame.Centre() self. 'Line') app.PaintDC device context. title): wx. that each time our window is repainted. 60.__init__(self. size=(250.Show(True) def OnPaint(self. 60) app = wx. event): dc = wx.OnPaint) self. Figure: drawing a line 4 de 44 27/04/2008 1:08 . parent.MainLoop() self. 190.com/wxpython/gdi/ #!/usr/bin/python # line2. maximize it). zetcode. Vector graphics is the use of geometrical primitives There are two different computer graphics.Brush wx. curves or polygons to represent images.com/wxpython/gdi/ 2D Vector Graphics graphics.The Graphics Device Interface http://www.Colour GetTextBackground() wx.Colour wx. scaling. filling or rotating does not degrade the Types of primitives points lines polylines circles polygons ellipses Splines Device context attributes Attribute Object Default value Get Method Brush Pen Mapping Mode BackgroundMode Text background colour Text foreground colour wx.BLACK wx.Colour GetTextForeground() BAS IC EL E ME NT S 5 de 44 27/04/2008 1:08 . lines.Pen GetPen() int GetMapMode() int GetBackgroundMode() wx. These primitives are created using mathematical equations.Brush GetBrush() wx.TRANSPARENT wx. The advantages of vector graphics over raster smaller size ability to zoom indefinitely quality of an image moving.WHITE wx.Pen wx.Colour wx.WHITE_BRUSH wx. Raster graphics represents images as a collection of pixels.MM_TEXT wx. Both types of computer graphics have advantages and are: disadvantages.BLACK_PEN wx. Vector and raster such as points. colour. Joins. These three notations produce the same colour name or use hex value string.0. Pens. Caps. Gradients.255). Colours A colour is an object representing a combination of Red. Brushes. '#0000FF'. Colours. Valid RGB values are colours.Colour object.zetcode. I prefer the hexadecimal notation. Or we We have also a list of predefined colour names that we can use in our programs.com website. in the range 0 to 255. We can create a wx. A perfect tool for working can use such a tool as Gimp. There are three ways for setting Green. with colours can be found on the colorjack. and Blue (RGB) intensity values. 6 de 44 27/04/2008 1:08 . wx.Colour(0.com/wxpython/gdi/ In the following lines we will introduce several elementary objects. use a predefined 'BLUE'.The Graphics Device Interface http://www. zetcode.Centre() self.__init__(self. title. 280)) self. parent.py import wx class Colours(wx.com/wxpython/gdi/ AQUAMARINE CADET BLUE BLACK CORAL DARK OLIVE GREEN DIM GREY GREY BLUE CORNFLOWER BLUE DARK ORCHID BLUE VIOLET CYAN DARK SLATE BLUE FOREST GREEN GREEN YELLOW LIGHT STEEL BLUE MEDIUM BLUE MEDIUM SLATE BLUE NAVY PINK SEA GREEN STEEL BLUE VIOLET RED BROWN DARK GREY DARK SLATE GREY GOLD INDIAN RED LIME GREEN MEDIUM FOREST GREEN MEDIUM SPRING GREEN ORANGE PLUM SIENNA TAN WHEAT DARK GREEN DARK TURQUOISE GOLDENROD FIREBRICK GREEN KHAKI LIGHT BLUE LIGHT GREY MAGENTA MAROON MEDIUM AQUAMARINE MEDIUM SEA GREEN MIDNIGHT BLUE PALE GREEN SALMON SPRING GREEN VIOLET YELLOW GREEN MEDIUM GOLDENROD MEDIUM TURQUOISE ORANGE RED PURPLE SKY BLUE THISTLE WHITE MEDIUM ORCHID MEDIUM VIOLET RED ORCHID RED SLATE BLUE TURQUOISE YELLOW #!/usr/bin/python # colours. self. title): wx.Frame.Frame): def __init__(self. id. id. size=(350.OnPaint) self.Show(True) def OnPaint(self. event): 7 de 44 27/04/2008 1:08 .The Graphics Device Interface Standard Colour Database http://www. parent.EVT_PAINT.Bind(wx. 90.com/wxpython/gdi/ dc = wx. 60) dc. 90.Brush('#4c4c4c')) dc.DrawRectangle(10. 60) dc.App() Colours(None.zetcode. 60) app = wx. 105. 90. 195.MainLoop() Figure: Colours 8 de 44 27/04/2008 1:08 .DrawRectangle(130.DrawRectangle(130. 15. 195.SetBrush(wx.Brush('#5f3b00')) dc. 60) dc. 105. 'Colours') app. -1.SetBrush(wx.SetBrush(wx.DrawRectangle(10.SetBrush(wx. 90. 90.DrawRectangle(250.Brush('#1ac500')) dc. 15. 60) dc. 90.Brush('#785f36')) dc. 90.SetBrush(wx. 90.SetBrush(wx. 60) dc.DrawRectangle(130. 60) dc.PaintDC(self) dc. 90.Brush('#539e47')) dc.SetBrush(wx. 105. 15.Pen('#d4d4d4')) dc.SetBrush(wx.DrawRectangle(250.DrawRectangle(250.Brush('#9e4757')) dc.SetPen(wx.Brush('#c50024')) dc. 60) dc. 195. 60) dc.SetBrush(wx.The Graphics Device Interface http://www.DrawRectangle(10.Brush('#004fc5')) dc.Brush('#c56c00')) dc. curves and outlines of rectangles. 90. wx. wx.Pen(wx. 60) dc.Frame): def __init__(self. 1.LONG_DASH)) dc.SOLID)) dc.DOT wx.com/wxpython/gdi/ wx.OnPaint) self. Colour. id.Show(True) def OnPaint(self.DrawRectangle(130.Pen('#4c4c4c'.SOLID) The wx.Pen Pen is an elementary graphics object.SetPen(wx.SetPen(wx. 60) dc.SHORT_DASH)) 9 de 44 27/04/2008 1:08 .SHORT_DASH wx.SOLID wx. 15.DrawRectangle(10. width and style. id.DOT_DASH wx. wx.Bind(wx.Pen('#4c4c4c'.__init__(self. polygons or other shapes. 190)) self. title.SetPen(wx. It is used to draw lines. ellipses.Pen('#4c4c4c'. wx. 1.Pen constructor has three parameters. wx.TRANSPARENT #!/usr/bin/python # pens. 15. event): dc = wx. title): wx.SetPen(wx.py import wx class Pens(wx. Follows a list of possible pen styles. 1. widht=1. 1. parent. 60) dc.EVT_PAINT.zetcode.Colour colour.PaintDC(self) dc.DOT)) dc. Pen styles wx.The Graphics Device Interface http://www.Centre() self.Pen('#4c4c4c'. 90. style=wx.DrawRectangle(250. self. parent.LONG_DASH wx.Frame. 15. 90. size=(350. WHITE_BRUSH.Pen('#4c4c4c'. 60) app = wx. The Join and the Cap.SetPen(wx.zetcode. wx. They meet at an angle.JOIN_ROUND. not visible. In wx.JOIN_ROUND When using wx. 'Pens') app.com/wxpython/gdi/ dc. -1. 1. The Join defines how joins between lines will be drawn.DrawRectangle(130.The Graphics Device Interface http://www.DOT_DASH)) dc.App() Pens(None.JOIN_BEVEL wx. 105. The default brush is wx. 90. 60) dc. 60) dc. 90. rectangles is drawn by the pen.JOIN_BEVEL the triangular notch between two lines is lines is filled.MainLoop() If we don't specify a custom brush. 105. The default value is wx.DrawRectangle(10. 105. In wx. wx. e. It Figure: Pens Joins and Caps A pen object has additional two parameters. 10 de 44 27/04/2008 1:08 . The last one has no border.Pen('#4c4c4c'. The Join style has the following options: wx.g.TRANSPARENT)) dc.JOIN_ROUND the circular arc between the two The Cap defines how the line ends will be drawn by the pen. 1. a default one is used.SetPen(wx.DrawRectangle(250. and this area is filled. 90.JOIN_MITER the outer edges of the lines are extended.JOIN_MITER wx. The perimeter of the is transparent. filled. 150.CAP_BUTT will both draw wx. 150.zetcode. wx.OnPaint) self.DrawRectangle(15. id.JOIN_MITER) dc.SetCap(wx. 190) 11 de 44 27/04/2008 1:08 . 15. title): wx. #!/usr/bin/python # joinscaps.Frame.__init__(self. 150) pen.CAP_ROUND will extend beyond the end point as well. title.SetJoin(wx.SetPen(pen) dc.CAP_PROJECTING) dc.Centre() self.CAP_BUTT) dc.EVT_PAINT.SetCap(wx.CAP_PROJECTING and the wx. id.CAP_PROJECTING will extend beyond the end point by the half of the line size.DrawRectangle(235.JOIN_ROUND) dc.Pen('#4c4c4c'.DrawLine(30. 15.Show(True) def OnPaint(self.PaintDC(self) pen = wx. parent. 50) pen.CAP_ROUND will draw rounded ends. 80. 10.SetPen(pen) dc.SetJoin(wx.SetPen(pen) dc.py import wx class JoinsCaps(wx.The Graphics Device Interface The options are: wx. 300)) self.DrawLine(30. parent. 50) pen. 15. event): dc = wx.JOIN_BEVEL) dc. 80.Frame): def __init__(self.SetJoin(wx.DrawRectangle(125.SetPen(pen) dc. The square ends.CAP_BUTT http://www. The difference between them is that the wx.Bind(wx. self.SOLID) pen. 50) pen. 190. 150. size=(330.SetPen(pen) dc.CAP_ROUND wx.CAP_PROJECTING The wx.com/wxpython/gdi/ wx. The wx. 80. dc. 230. It is exactly the half of the current pen width.SOLID) dc. 155. 250) dc. 250) app = wx. 130.DrawLine(155. 'Joins and Caps') app. we need to set the pen width to be greater than 1.SetPen(pen2) dc. wx.zetcode. 1.SetPen(pen) dc. 250) dc.App() JoinsCaps(None. 30. 130. 250) Notice the two enclosing vertical lines. Figure: Joins and Caps Gradients In computer graphics. 10.com/wxpython/gdi/ pen. 150.DrawLine(30.CAP_ROUND) dc. 150.The Graphics Device Interface http://www.Pen('#4c4c4c'.DrawLine(30.SetCap(wx. The distance between them is 5px.Pen('#4c4c4c'. 130.DrawLine(150. gradient is a smooth blending of shades 12 de 44 27/04/2008 1:08 .MainLoop() pen = wx. wx. 130. 230) pen2 = wx. 130. 150.DrawLine(150. -1. 250) dc. 155.DrawLine(155.SOLID) In order to see the various Join and Cap styles. In 2D drawing programs and paint programs. 40). starting from initialColour and eventually fading to #!/usr/bin/python # gradients.Colour initialColour. parent. '#000000'. wx. title): wx. parent.com) colorful backgrounds and special effects as well as to simulate GradientFillLinear(wx.com/wxpython/gdi/ from light to dark or from one color to another. 'Gradients') app.EVT_PAINT.Centre() self. gradients are used to create lights and shadows. '#000000'. '#ffec00'. -1. 40).GradientFillLinear((20. wx.MainLoop() 13 de 44 27/04/2008 1:08 . dc. wx.GradientFillLinear((20. self. dc.EAST.__init__(self.Bind(wx.Frame.OnPaint) self.Colour destColour.EAST 200. '#ffec00'. 40). '#ffec00'. id. event): dc = wx. (answers. 20.Show(True) def OnPaint(self. The nDirection parameter specifies the direction of the colour change. size=(220. '#000000'.SOUTH 140.zetcode. wx.The Graphics Device Interface http://www.Frame): def __init__(self. title.WEST app = wx. 180.GradientFillLinear((20. 180.App() Gradients(None.PaintDC(self) dc. gradient. 180. 40).NORTH 80.py import wx class Gradients(wx. '#000000'. 260)) self. the default value is wx. dc. wx. '#ffec00'. 180. This method fills the area specified by a rect with a linear destColour.Rect rect. id.GradientFillLinear((20. wx. The Graphics Device Interface http://www. The following is a list of possible brush styles.SOLID wx.SOLID) The constructor of the wx.Brush Brush is an elementary graphics object.Colour colour.py 14 de 44 27/04/2008 1:08 .Brush(wx.CROSSDIAG_HATCH wx.com/wxpython/gdi/ Figure: Gradients wx. Brush styles wx.zetcode.VERTICAL_HATCH wx. It is used to paint the polygons. Colour name and style. ellipses or wx.FDIAGONAL_HATCH wx.STIPPLE wx.BDIAGONAL_HATCH wx. style=wx.CROSS_HATCH wx.HORIZONTAL_HATCH wx. background of graphics shapes. such as rectangles.Brush accepts two parameters.TRANSPARENT #!/usr/bin/python # brushes. 60) dc.SetBrush(wx.Brush('#4c4c4c'. 105.SetBrush(wx.The Graphics Device Interface http://www. 60) dc.DrawRectangle(10.DrawRectangle(130. 90.DrawRectangle(130.MainLoop() 15 de 44 27/04/2008 1:08 . id. 90.SetBrush(wx.Bind(wx.DrawRectangle(130.__init__(self. wx. wx. title. id.Brush('#4c4c4c'.BDIAGONAL_HATCH)) dc.Brush('#4c4c4c'.Brush('#4c4c4c'. 280)) self.VERTICAL_HATCH)) dc.OnPaint) self. 15. 'Brushes') app.Brush('#4c4c4c'. self.Centre() self. 90. 105.com/wxpython/gdi/ import wx class Brush(wx. 60) dc.SetBrush(wx. wx.DrawRectangle(250. -1.SetBrush(wx. 15. 195. wx. 195. 60) dc.Brush('#4c4c4c'. 105.Brush('#4c4c4c'.Brush('#4c4c4c'. 60) app = wx. size=(350. 60) dc.SetBrush(wx. 90. 90. title): wx.DrawRectangle(10.DrawRectangle(10. parent. parent.SOLID)) dc.Show(True) def OnPaint(self. wx.DrawRectangle(250.Frame. 90.PaintDC(self) dc.EVT_PAINT. 15. 60) dc.App() Brush(None. wx.CROSSDIAG_HATCH)) dc.SetBrush(wx. 90. wx. event): dc = wx.CROSS_HATCH)) dc.SetBrush(wx. 60) dc. 90.FDIAGONAL_HATCH)) dc.zetcode.Frame): def __init__(self.TRANSPARENT)) dc. wx.HORIZONTAL_HATCH)) dc. Bind(wx.Bitmap('pattern1.The Graphics Device Interface http://www.Bitmap stippleBitmap) This method creates a custom brush from the bitmap. parent. We can easily create our own custom patterns.zetcode.EVT_PAINT.BrushFromBitmap(wx.Frame.Pen('#C7C3C3')) brush1 = wx.com/wxpython/gdi/ Figure: Brushes Custom Patterns We are not restricted to use predefined patterns. title. title): wx.py import wx class CustomPatterns(wx.png')) 16 de 44 27/04/2008 1:08 . wx.Show(True) def OnPaint(self. id.PaintDC(self) dc. size=(350. #!/usr/bin/python # custompatterns.Frame): def __init__(self.SetPen(wx. event): dc = wx.__init__(self.Brush BrushFromBitmap(wx. self. 280)) self.Centre() self. parent. id.OnPaint) self. BrushFromBitmap(wx. 'Custom Patterns') app.DrawRectangle(250.BrushFromBitmap(wx.SetBrush(brush1) dc. 90.png')) dc. usually around 40-150px. 60) brush4 = wx.Bitmap('pattern5. 90.SetBrush(brush8) dc.BrushFromBitmap(wx.BrushFromBitmap(wx.DrawRectangle(250. 105. 90. 15.Bitmap('pattern4.BrushFromBitmap(wx.SetBrush(brush2) dc. These bitmaps are rectangles.png')) dc. For this I used the Gimp. 195. -1.SetBrush(brushr9) dc.com/wxpython/gdi/ dc.MainLoop() I have created some small bitmaps. 60) brush2 = wx. 90.SetBrush(brush4) dc. 90.Bitmap('pattern6.DrawRectangle(10.Bitmap('pattern8.png')) dc.png')) dc. 90.zetcode.Bitmap('pattern2.SetBrush(brush6) dc.SetBrush(brush3) dc.png')) dc. 60) brush7 = wx.Bitmap('pattern7. 60) brush5 = wx. 15.DrawRectangle(130.App() CustomPatterns(None.DrawRectangle(10. 60) brush3 = wx. 60) app = wx.png')) dc.BrushFromBitmap(wx. 60) brush6 = wx.Bitmap('pattern9.BrushFromBitmap(wx.DrawRectangle(10.png')) dc.The Graphics Device Interface http://www. 105. 60) brush8 = wx. 17 de 44 27/04/2008 1:08 .BrushFromBitmap(wx. 105. 90. 90.DrawRectangle(130.DrawRectangle(130. 15.png')) dc.SetBrush(brush7) dc.SetBrush(brush5) dc. 60) brushr9 = wx.Bitmap('pattern3. 195.DrawRectangle(250. 90. 195. Bind(wx.Centre() self.__init__(self. self. 150)) self.py import wx import random class Points(wx. #!/usr/bin/python # points. It is a plain dot on the window.OnPaint) self.com/wxpython/gdi/ Figure: Custom Patterns Basic primitives Point The simplest geometrical object is a point. id. DrawPoint(int x. title. parent.Frame): def __init__(self. size=(250. y coordinates.Show(True) 18 de 44 27/04/2008 1:08 .EVT_PAINT. int y) This method draws a point at x. title): wx. id. parent.zetcode.Frame.The Graphics Device Interface http://www. the points will be drawn randomly over a new in range [a. The randint(a.Pen('RED')) Here we set the colour of the pen to red. dc. h = self. w-1) y = random. event): dc = wx.SetPen(wx. 19 de 44 27/04/2008 1:08 . b]. h = self. -1.randint(1.DrawPoint(x. y) app = wx.randint(1.randint(1. including both points.zetcode. They are also distributed dynamically.com/wxpython/gdi/ def OnPaint(self.g.GetSize() x = random.SetPen(wx. It is centered on the given point.App() Points(None. So we create 1000 points.GetSize() x = random. w-1) The points are distributed randomly around the client area of the window. the window. e. w. 'Points') app. b) method returns a random integer Figure: drawing points Cross Hair Cross Hair is a vertical and horizontal line the height and width of the window. h-1) dc. If we resize client size.PaintDC(self) dc.Pen('RED')) for i in range(1000): w.The Graphics Device Interface http://www.MainLoop() A single point might be difficult to see. com/wxpython/gdi/ CrossHair(int x. title): wx.EVT_PAINT.zetcode.Frame): def __init__(self.' #!/usr/bin/python # crosshair2. size=(250.__init__(self. 50) app = wx. #!/usr/bin/python # crosshair. -1. self.PaintDC(self) dc. title. parent. y.MainLoop() Figure: A Cross Hair In the following code example we will create a functionality often seen in games.Centre() self.Bind(wx. 150)) self.Show(True) def OnPaint(self.py 20 de 44 27/04/2008 1:08 .Frame. id. int y) The method draws a cross hair centered on coordinates x. parent.The Graphics Device Interface http://www.App() CrossHair(None. 'Aiming at the enemy.CrossHair(50. 'CrossHair') app.py import wx class CrossHair(wx. event): dc = wx. id.OnPaint) self. y) def OnLeaveWindow(self.OnMotion) self. title): wx. y = event.SetCursor(wx. which is responsible for drawing the cross hair.DOT)) dc.Clear() dc. event is generated.CURSOR_CROSS)) self.SetBackgroundColour('WHITE') self.OnLeaveWindow) We bind two events to event handlers.SetBackground(wx.Frame): def __init__(self.GetPosition() self. y = event. wx.App() CrossHair(None.EVT_LEAVE_WINDOW.Clear() app = wx. event): x. a.OnLeaveWindow) self. self. self.Bind(wx.EVT_MOTION.Frame.DrawCrossHair(x.Show(True) def DrawCrossHair(self.ClientDC(self) dc.StockCursor(wx. id.DrawCrossHair(x. b): dc = wx. -1.Brush('WHITE')) dc. the method position of the mouse cursor and call the DrawCrossHair method.Bind(wx.ClientDC(self) dc.Colour(100.Bind(wx.Centre() self. size=(250.GetPosition() self. when we move a cursor over the window.SetPen(wx.OnMotion) self.com/wxpython/gdi/ import wx class CrossHair(wx. 1. In this method we figure out the current 21 de 44 27/04/2008 1:08 . event): dc = wx.Bind(wx.The Graphics Device Interface http://www.EVT_LEAVE_WINDOW. y) Every time we move a cursor over a window. The wx. OnMotion() is called.EVT_MOTION.Pen(wx. title.__init__(self. 100.EVT_LEAVE_WINDOW is generated.EVT_MOTION The second event wx. 150)) self.CrossHair(a. parent.MainLoop() self. def OnMotion(self. b) def OnMotion(self. parent. 100). self. event): x. 'CrossHair2') app. id.zetcode. self. when we leave the window with our mouse cursor. we use the wx. int y.zetcode. wx. self. we must clear the old one. 1. unless we set a different one. dotted.SetPen(wx. a.OnPaint) self.Frame. title): wx. Before we draw a new cross hair drawing. Remember that this device context should be used outside the paint event. parent. to light gray color. Not wx.ClientDC. id. int width. window at coordinates x. where we use wx. 150)) self.DOT)) dc. This script is a perfect example. b): dc = wx. which draws the cross hair. In order to actually see it.PaintDC. y. This is done with the Clear() method.ClientDC(self) dc. Notice that to do the drawing.EVT_PAINT. cursor to wx. parent. 100). size=(250.Show(True) 22 de 44 27/04/2008 1:08 .__init__(self.py import wx class CheckMark(wx. title.The Graphics Device Interface http://www.CURSOR_CROSS.WHITE_BRUSH brush. We have set the window have set the pen.Centre() self. 1px wide.Pen(wx. It draws the check mark inside the #!/usr/bin/python # checkmark. It uses the default wx.Clear() dc.Colour(100. int height) The DrawCheckMark() method draws a check mark on the rectangle defined by width and height parameters.com/wxpython/gdi/ def DrawCrossHair(self. 100.CrossHair(a. b) The user defined method DrawCrossHair() draws the cross hair primitive.Bind(wx. id.Frame): def __init__(self.ClientDC device context. Chech Mark Check Mark is another simple primitive. It does clear the device context area. we DrawCheckMark(int x. 30.App() CheckMark(None.MainLoop() Figure: Check Mark S HAPE S Shapes are more sophisticated geometrical objects. 20. 20.PaintDC(self) dc. id. parent. 300)) self. id. 60) dc.zetcode. size=(350. 90. 20) 23 de 44 27/04/2008 1:08 . -1.py import wx class Shapes(wx. 40. 40. self.DrawRoundedRectangle(130.DrawEllipse(20. event): dc = wx.DrawArc(240. 'Check Mark') app.Show(True) def OnPaint(self. 340.Frame): def __init__(self. title. 60.OnPaint) self. title): wx. 90. 290.DrawCheckMark(100.__init__(self.The Graphics Device Interface http://www.Frame.com/wxpython/gdi/ def OnPaint(self. 10) dc. parent.Centre() self.PaintDC(self) dc. We will draw various geometrical shapes in the following example. event): dc = wx. #!/usr/bin/python # shapes.EVT_PAINT. 50.Bind(wx. 40) app = wx. Intersect. 35) dc. 120.DrawRectangle(20. 140). lines. 60) app = wx. circle is a special kind of ellipse and a square is a special kind Figure: Shapes RE G IONS The device context can be divided into several parts called Regions. 110))) dc. filling or clipping. 260).DrawSpline(((240. a circle and a square (from right to left. (280. (180. 'Shapes') app. (100. 200. 60. A of rectangle.App() Shapes(None. 170). 170).The Graphics Device Interface http://www. 110). 110). Regions are used for outlining. a rounded rectangle. 140). (325. a rectangle . 50) dc.DrawCircle(170. With Union.zetcode. 80. 210). A region can be a and Xor operations we can create complex regions from simple rectangle or circle. from top to bottom). -1. (180. (20. (100.a polygon. 24 de 44 27/04/2008 1:08 . (140. 1 dc.DrawLines(((20. an arc. (285. Substract simple ones. (220. 210))) dc. splines.MainLoop() In our example we have drawn an ellipse. 230.DrawRectangle(250. A region can be of any shape. 170).com/wxpython/gdi/ dc.DrawPolygon(((130. 260). PaintDC(self) size_x. size=(450.__init__(self. int fillStyle=wx. size_y = self. size_y/2) 25 de 44 27/04/2008 1:08 . int y=0. self.py import wx from math import hypot. id.Show(True) def OnPaint(self.RegionFromPoints(list points. event): dc = wx.Bitmap bmp) The most complex regions can be created with the previous method. wx.Region(int x=0. cos.Bind(wx.Frame): def __init__(self.zetcode. sin. title. id.Centre() self. Here we can find a good article. Before we go to the regions.ODDEVEN_RULE.WINDING_RULE or wx.OnPaint) self. The fillStyle parameter can be wx.The Graphics Device Interface http://www. 400)) self. wx. size_y/2) radius = hypot(size_x/2.com/wxpython/gdi/ We can create regions in three ways. We divide the topic into several parts so that it is easier #!/usr/bin/python # lines. parent.EVT_PAINT.SetDeviceOrigin(size_x/2. parent. title): wx.Frame. You may find it a good idea to revise your school math. int height=0) This constructor creates a rectangular region. int width=0. More complex regions can be created from a list of points of from a bitmap. first.WINDING_RULE) This constructor creates a polygonal region. pi class Lines(wx. we will create a small example to understand.RegionFromBitmap(wx.GetClientSizeTuple() dc. wx. The easiest way is to create a rectangular region. App() Lines(None. 0). 'Lines') app.com/wxpython/gdi/ angle = 0 while (angle < 2*pi): x = radius*cos(angle) y = radius*sin(angle) dc. area. that should be drawn from the beginning into the corner The overlapping parts are not visible.zetcode. client area. This way most of the lines are not drawn fully. -1. We place it into the middle of the client drawing less complicated. sin. x = radius*cos(angle) y = radius*sin(angle) These are parametric functions. of the window. It is the longest line. The distance between two lines is 1 degree. size_y/2) Here we get the Hypotenuse.SetDeviceOrigin(size_x/2. dc. we make our radius = hypot(size_x/2.MainLoop() In this example we draw 260 lines from the middle of the create an interesting figure. beginning of the coordinate system up to the points on the 26 de 44 27/04/2008 1:08 . see Hypotenuse. They are used to find [x. It is the length of the line. y] points on the curve. (x. we can draw from the middle of the client area. pi We need three mathematical functions and one constant from the math module. All 360 lines are drawn from the circle. size_y/2) The method SetDeviceOrigin() creates a new beginning of the coordinate system. By repositioning the coordinate system.The Graphics Device Interface http://www. We import wx from math import hypot. y)) angle = angle + 2*pi/360 app = wx. cos.DrawLinePoint((0. Centre() 27 de 44 27/04/2008 1:08 .Bind(wx. id. title): wx.Frame): def __init__(self.zetcode.__init__(self. #!/usr/bin/python # star. Clipping is used in two cases.OnPaint) self. To create effects and to improve performance of the application.The Graphics Device Interface http://www. self. parent. cos. title. size=(350. 300)) self. pi class Star(wx. sin.EVT_PAINT. id.py import wx from math import hypot. We restrict drawing to a certain region with the SetClippingRegionAsRegion() method. In the following example we will modify and enhance our previous script.com/wxpython/gdi/ Figure: Lines Clipping Clipping is restricting drawing to a certain area.Frame. parent. The Graphics Device Interface http://www. 75). 28 de 44 27/04/2008 1:08 . (100. 190).PaintDC(self) dc. dc.DestroyClippingRegion() We must destroy the clipping region. 150). 0). event): dc = wx. The region that we restrict our drawing to is a star object.MainLoop() We draw again all the 360 lines.RegionFromPoints(points) dc. (125. In our case it is a star object. 125). The SetClippingRegionAsRegion() method restricts the drawing to the specified region.SetDeviceOrigin(size_x/2.Pen('#424242')) size_x. 190). (75. only a portion of the client aren is drawn. (200. (100.com/wxpython/gdi/ self.SetClippingRegionAsRegion(region) radius = hypot(size_x/2.RegionFromPoints(points) dc. 'Star') app. -1. 85).GetClientSizeTuple() dc.SetPen(wx.SetClippingRegionAsRegion(region) We create a region from the list of points with the wx. 10). (150. (160.zetcode. (50. size_y/2) angle = 0 while (angle < 2*pi): x = radius*cos(angle) y = radius*sin(angle) dc. region = wx. 75).DestroyClippingRegion() app = wx. (x.DrawLinePoint((0.Show(True) def OnPaint(self. size_y = self.RegionFromPoins() method. 125))) region = wx. 85). But this time. size_y/2) points = (((0. y)) angle = angle + 2*pi/360 dc.App() Star(None. (40. The Graphics Device Interface http://www. 50.DrawRectangle(30. title. parent. 40.zetcode. Intersect.EVT_PAINT. id. id. size=(270. title): wx.Pen('#d4d4d4')) dc.__init__(self. can use four set operations. parent. 50. 50) dc. #!/usr/bin/python # operations.py import wx class Operations(wx.PaintDC(self) dc.SetBrush(wx. We Xor.Centre() self.Frame.SetPen(wx.Frame): def __init__(self. Union. 20. self.Bind(wx.Brush('#ffffff')) 29 de 44 27/04/2008 1:08 .com/wxpython/gdi/ Figure: Star Operations over Regions Regions can be combined to create more complex shapes.OnPaint) self.DrawRectangle(20. 220)) self. event): dc = wx. Substract and The following example shows all four operations in action.Show(True) def OnPaint(self. 50) dc. Brush('#ffffff')) dc. 50) dc. 120. 120.UnionRegion(region2) dc.SetClippingRegionAsRegion(region1) dc. 140. 50) region1.Region(100.SetBrush(wx.GetBox() dc.Region(30.SetBrush(wx.SubtractRegion(region2) rect = region1. 20. 50) region2.Region(100.DestroyClippingRegion() dc.Brush('#ffffff')) dc.Region(190.Brush('#619e1b')) dc. 50. 50) region1 = wx. 50) region2 = wx.DestroyClippingRegion() dc.DrawRectangleRect(rect) dc.DestroyClippingRegion() dc.DrawRectangle(20.DrawRectangleRect(rect) dc.Region(110.SetBrush(wx.SetClippingRegionAsRegion(region1) rect = region1. 140. 50.DrawRectangleRect(rect) dc. 50.Region(180.SetBrush(wx. 50) region1 = wx.GetBox() dc. 50.GetBox() dc. 140.DrawRectangle(110.SetClippingRegionAsRegion(region1) dc.Brush('#fa8e00')) dc. 50) region1. 50) dc. 50) region2 = wx.The Graphics Device Interface http://www. 50.GetBox() dc.SubtractRegion(region1) rect = region2.IntersectRegion(region2) rect = region1.SetClippingRegionAsRegion(region2) dc. 40.Brush('#715b33')) dc. 50. 120.DrawRectangleRect(rect) dc.DrawRectangle(110. 50) dc. 50. 50) region1 = wx. 50.SetBrush(wx.Brush('#ffffff')) dc. 50. 50) region1.DrawRectangle(100. 50.SetBrush(wx. 50. 140.DrawRectangle(190.Brush('#ffffff')) dc. 50. 20. 120. 140. 50.Brush('#ff0000')) dc. 50) region1 = wx. 50) region2 = wx. 50) dc.SetBrush(wx. 20. 50) region1.SetBrush(wx. 50) region2 = wx.Region(110.XorRegion(region2) rect = region1.SetClippingRegionAsRegion(region1) dc.com/wxpython/gdi/ dc.Brush('#0d0060')) 30 de 44 27/04/2008 1:08 . 50. 50. 50) region2 = wx. 20. 40. 50) region1 = wx.DrawRectangle(180. 50. 40.DrawRectangle(30.zetcode. 120. 140.GetBox() dc. 50) dc.Region(20. 50. 50.Region(180.DrawRectangle(100.SetBrush(wx. 50. 50. 120.DrawRectangle(190.DestroyClippingRegion() dc. 40.Region(190.DrawRectangle(180. measure temperature. It is one hundred and .. "It is very hot today. 'Operations') app.The Graphics Device Interface http://www... gallons to tank their cars or pounds to This might lead to some funny situations. Americans use Fahrenheits to weigh loads. So did the metric system become the global there are only three exceptions.wait one hundred and .MainLoop() Figure: Set operations on Regions M AP PI N G M OD E S Speak in English.zetcode." ". there are 31 de 44 27/04/2008 1:08 . According to this wikipedia article. five Fahrenheits. Myanmar.DrawRectangleRect(rect) dc." "Aha.DestroyClippingRegion() app = wx. -1. For example." (When I was in US talking to an American) Even though we in Europe use the metric system..com/wxpython/gdi/ dc. What is the temperature?" ?!?! "Let me see. The USA.App() Operations(None. Liberia and system in measuremet. measure in Metric The English language became the global language for communication. x.MM_TWIPS 1 pixel 1 millimeter 1/10 of a millimeter 1 point. wxPython has the following mapping modes: mapping mode of the device is a way how to convert logical Mapping Mode Logical Unit wx. videocameras. device units are are native to a particular device. The device then the same. The USA is dominating the IT and we are http://www. So we also say that we have a 17 Inch monitor. draws the text in device units. Logical units are used by people (millimeters). The native device unit for the HEWLETT PACKARD LaserJet 1022 is 1200 dpi. we provide the text parameter and the x.com/wxpython/gdi/ importing their standards.MM_POINTS wx. mobile phones) or printed with a printer. We have also dots. When people position object on a screen or design a web page.MM_TEXT.zetcode. In this mode. The units to device units. the resolution of a screen is in pixels. we position them using logical units. points or inches. or they may differ. the logical unit is the same as the device unit. Logical and device units may be So far we have talked about various measurement units. y are in logical units. Logical and device units If we draw text or geometrical primitives on the client area. displayed on the screen of a monitor or other device (cameras.The Graphics Device Interface still exceptions. For example a native device unit for a screen is pixel.MM_LOMETRIC wx. Web designers create three column pages 32 de 44 27/04/2008 1:08 .MM_METRIC wx. Graphics can be put into a file. (dots per inch). they think usually in pixels. y positions. This is one If we want to draw some text. 1/72 of an inch 1/20 of a point or 1/1440 of an inch The default mapping mode is wx.MM_TEXT wx. dots per inch. bits or samples. Paper size can be set in millimeters. the quality of a text is determined by the number of of the reasons we have logical and device units. self.FRAME_NO_TASKBAR | wx. First ruler example The first ruler example will measure screen objects in pixels. This thinking is natural as we know our monitors have e. title): wx.EVT_PAINT.PaintDC(self) brush = wx. We are not going to do convertions. we can use the two metric mapping modes.EVT_MOTION.Show(True) def OnPaint(self.OnLeftDown) self.OnRightDown) self. wx. parent.STAY_ON_TOP) self.The Graphics Device Interface and these columns are set in pixels. style=wx. False.FONTWEIGHT_BOLD.OnPaint) self. id.NO_BORDER | wx. title.MM_LOMETRIC mapping mode. 1024x768 pxs. we use the SetMapMode() method.Bitmap('granite. #!/usr/bin/python # ruler1. self.font = wx.__init__(self.OnMouseMove) self.zetcode. 60).g.Frame): def __init__(self.Bind(wx. The lowest common http://www.FONTFAMILY_DEFAULT. wx.Bind(wx.png')) 33 de 44 27/04/2008 1:08 . self. Drawing directly wx. self.Font(7.com/wxpython/gdi/ denominator for a page is often 800 px etc. 'Courier 10 Pitch') self. rather we are accustomed to think in pixels.EVT_LEFT_DOWN. If we want to draw a structure in millimeters. that's why we have the To set a different mapping mode. size=(RW + 2*RM.EVT_RIGHT_DOWN.Frame.FONTSTYLE_NORMAL. parent. in millimeters is too thick for a screen.Bind(wx.py import wx RW = 701 # ruler widht RM = 10 # ruler margin RH = 60 # ruler height class Ruler1(wx. wx.Centre() self. event): dc = wx. id.BrushFromBitmap(wx.Bind(wx. y . event): if event.. The ruler is 721 px shows 700 numbers. 0. This ruler will measure screen objects in pixels.ClientToScreen(event. i+RM. y = self. We left the default mapping mode. RW+2*RM.SetBrush(brush) dc. size=(RW + 2*RM. The ruler is RW + 2*RM = 701 + 20 = 721.DrawText(str(i). 0.delta = ((dx.self. RH) dc. As we have already mentioned.__init__(self.ox dy = y .FRAME wx. i+RM-w/2.Frame. style=wx.LeftIsDown(): x. h = dc. The ruler 34 de 44 27/04/2008 1:08 .oy self.Move(fp) def OnRightDown(self.delta[1]) self. In our case. title. which is wx. A ruler has a wide.ClientToScreen(event.DrawLine(i+RM.Pen('#F8FF25')) dc.self. y = self.SetTextForeground('#F8FF25') for i in range(RW): if not (i % 100): dc.GetTextExtent(str(i)) dc.STAY_ON_TOP) We have created a borderless window.GetPosition()) ox. 11) elif not (i % 20): dc. event): pos = event.App() Ruler1(None. parent. -1. wx.GetPosition()) fp = (x . oy = self.MM_TEXT.font) dc. dy)) def OnMouseMove(self. i+RM.MainLoop() In this example we create a ruler. id. 0 .DrawLine(i+RM.GetPosition() x. 0. this mode has the same logical and device units. 60). pixels.delta[0]. event): self. '') app. i+RM. 0.zetcode..SetPen(wx.NO_BORDER | wx.DrawRectangle(0. 700 is 701 pixels. 10) w. 8) elif not (i % 2): dc.The Graphics Device Interface http://www. 4) def OnLeftDown(self.Close() app = wx.com/wxpython/gdi/ dc.DrawLine(i+RM.Dragging() and event.SetFont(self.GetPosition() dx = x . png')) dc. what we have learnt 35 de 44 27/04/2008 1:08 .com/wxpython/gdi/ margin on both sides.SetBrush(brush) dc. why do we need all those lines.The Graphics Device Interface http://www. Together it makes 721 pixels.DrawText(str(i). brush = wx. 11) These lines ensure. 0. So we must handle moving manually by additional code. i+RM-w/2. The OnLeftDown() and the OnMouseMove() methods enable us to move the ruler.DrawRectangle(0. It is called granite. (TODO:link to dragging. Charts are not GUI widgets. We will utilize.zetcode. No gui toolkit provides some practical examples. w. h = dc. pens. The the text.GetTextExtent(str(i)) dc. gradients? What is it good for? The following scripts will bring in practice. RH) Here we draw a custom pattern onto the window.) Figure: First ruler example PRACT ICAL E X AMPLE S You might ask yourself.BrushFromBitmap(wx. GetTextExtent() method returns the width and the height of We do not have a border around our window. that we align the text correctly. Charts Creating charts is an excelent example of utilizing gdi drawing functions.Bitmap('granite. RW+2*RM. 2*10 is 20 pixels. I have used a predefined pattern available in the GIMP. 134). 94)) years = ('2003'. 1) dc.Pen('WHITE')) dc. 65). has usually two options. 163). (300. parent) self. (170. (130. (20. (110.DrawAxis(dc) self. 30). (220. (40. 43). 71). (60. (30. 1. 21). (100.Panel.GetFont() font. (80. 1.DrawGrid(dc) self. 19).SetDeviceOrigin(40. 1. (200. True) dc. 130). 129).DrawTitle(dc) self. I kept the example intentionally the idea and follow it. We do not dwell into all details. 159). 41). (70. 89). (190. To create his own charting library or In the following example we create a simple line chart. 42). (210. (280. A lot of things still remain undone. (230. event): dc = wx. (160. (50. 45).SetPointSize(8) dc. parent): wx. 125).Pen('#0AB1FF')) font = dc. 22). (90.SetBackgroundColour('WHITE') self.__init__(self. 22). 9). 128).SetAxisOrientation(True.DrawData(dc) def DrawAxis(self. (180. 20).The Graphics Device Interface charts as part of the library. (250. But these charts are very http://www.OnPaint) def OnPaint(self. A developer use a third-party library.SetFont(font) dc. 201) 36 de 44 27/04/2008 1:08 .zetcode.DrawLine(1. 300. (120. self. (270. (290. But you can grasp #!/usr/bin/python # linechart. (240. 126).Bind(wx. (260.PaintDC(self) dc. 187).DrawLine(1.SetPen(wx.SetPen(wx.py import wx data = ((10. 62). simple. 200) self.Panel): def __init__(self.com/wxpython/gdi/ simple and cannot be used in real applications. 132). 240) dc.DrawRectangle(1. (150. 300. 150). 1. dc): dc. 53). One exception is wxWidgets toolkit (and so the wxPython). '2004'. 165). '2005') class LineChart(wx. 133).EVT_PAINT. (140. 2. title. 300. 'A line chart') app. title): wx.Pen('#0ab1ff')) for i in range(10. i. 310.ALL. 15) panel.SetBackgroundColour('WHITE') hbox = wx. 220. dc): font = dc.DrawLine(i.Add(linechart.Panel(self.SetPen(wx. id. 300. i) for i in range(100. -5.App() LineChartExample(None. -1.The Graphics Device Interface http://www. 10): dc.Show(True) app = wx.__init__(self. 100): dc.SetSizer(hbox) self. i+5) dc.DrawText(str(i).DrawLine(2.Frame): def __init__(self. 200) def DrawTitle(self. 2.GetFont() font. -30. 300. 300)) panel = wx.MainLoop() 37 de 44 27/04/2008 1:08 .DrawText('Historical Prices'.FONTWEIGHT_BOLD) dc. 220.BoxSizer(wx. i.zetcode.com/wxpython/gdi/ for i in range(20. i.HORIZONTAL) linechart = LineChart(panel) hbox.DrawLine(i. wx.SetFont(font) dc.DrawLine(2. i*100-13. size=(390. i. 1. -10) def DrawGrid(self. dc): dc.Centre() self. i) for i in range(100. dc): dc. parent. 20): dc. 90.SetPen(wx. -1) panel.EXPAND | wx.Pen('#d5d5d5')) for i in range(20. -5) for i in range(3): dc. 100): dc. 235) def DrawData(self.DrawSpline(data) class LineChartExample(wx. id. parent.DrawText(years[i].Frame.SetWeight(wx. 20): dc. The origin is dc.DrawText(years[i]. The first will draw axis.zetcode.) right and the orientation of y values is from top to bottom. This system is used in all GUI toolkits. orientation of y values is from bottom to top. 240) dc. The orientation of x values is from left to values can be only positive. We can put true or false values to these two parameters. we can have both positive and negative values. i*100-13.The Graphics Device Interface http://www. 240) dc. (All I am aware of.SetDeviceOrigin(40. -10) 38 de 44 27/04/2008 1:08 .com/wxpython/gdi/ dc. on the client area.DrawGrid(dc) self.DrawTitle(dc) self.DrawData(dc) We separate the construction of the chart into four methods. The beginning point is located at the upper left corner of the clinet area.SetDeviceOrigin(40. the third for i in range(3): dc.DrawAxis(dc) self.SetAxisOrientation(True. the second will draw the grid. The For charting we use cartesian coordinate system. In cartesian system. This is called linear translation. bool yBottomUp) The method signature is self-explanatory. The orientation of the x values is from left to right and the usually in the middle. 0]. the title and the last one will draw the data. But it is not compulsory. True) By default the coordinate system in wxPython begins at point [0. Then we SetAxisOrientation(bool xLeftRight.SetAxisOrientation(True. self. True) The SetDeviceOrigin() method moves the origin to a new point change the axis orientation with the SetAxisOrientation() method. there are some magic previous code example. how we can create a custom shaped visible notes. (e. It works on my linux box.g. I might not work correctly on other platforms. We subtract 13 px from the x value. we and center the text manually. In reality. we would have to calculate them. We will see. In the center the years over the vertical lines.com/wxpython/gdi/ Because of the simplicity of the script. the width of the text Figure: A line chart Note Note is a small script that shows several interesting features window.The Graphics Device Interface http://www. Normally. You just different circumstances is no rocket science. we draw the years alongside the x axis. This is done to numbers. Adjusting it to fit under the not work even on linux boxes with different themes. There are small applications that are used to take with computers a lot. of the GDI. They work as reminders for people. us).zetcode.py import wx 39 de 44 27/04/2008 1:08 . It might play a bit with this example. need to calculate the width of the chart. that work #!/usr/bin/python # note. zetcode. parent.bitmapRegion.Font(11.Bitmap('cross.SetClientSize((w.Offset(170. self.GetPosition() dx = x .bitmapRegion = wx.cross) self. id. *event): region = wx.GetSize() self.RegionFromBitmap(self.com/wxpython/gdi/ class Note(wx.GetPosition() if self.bitmapRegion.cross = wx. self.ContainsPoint(pos): self.bitmapRegion.Show(True) def PositionTopRight(self): disx. id.EVT_MOTION.BITMAP_TYPE_PNG) w = self. True) self. wx.crossRegion) self. parent. y = self.OnMouseMove) self. disy = wx. 0.bitmap. dy)) 40 de 44 27/04/2008 1:08 .OnPaint) self.GetWidth() h = self.SetNoteShape) else: self.ClientToScreen(event.IntersectRegion(self.Bind(wx.Bind(wx. wx.Bind(wx.EVT_WINDOW_CREATE.BITMAP_TYPE_PNG) self. style=wx.ox dy = y . wx. title.FONTFAMILY_DEFAULT.EVT_PAINT.Platform == '__WXGTK__': self. h)) if wx. False. oy = self.Frame.GetPosition()) ox. 10) dc = wx.__init__(self. 0)) def SetNoteShape(self. wx.bitmap) self.FRAME_NO_TASKBAR) self. event): pos = event.FRAME_SHAPED | wx.png'.SetShape(region) def OnLeftDown(self. self.FONTSTYLE_NORMAL.RegionFromBitmap(self.DrawBitmap(self.Bitmap('note.FONTWEIGHT_BOLD.Frame): def __init__(self.bitmap = wx.font = wx. wx. 'Comic Sans MS') self.GetHeight() self.RegionFromBitmap(self. y = self.SIMPLE_BORDER | wx.ClientDC(self) dc.bitmap.Close() x.oy self. self.Bind(wx.Move((disx-x.SetNoteShape() self.png'.delta = ((dx. 0.bitmap) self.GetDisplaySize() x.OnLeftDown) self.crossRegion = wx. title): wx.EVT_LEFT_DOWN.The Graphics Device Interface http://www.bitmap.PositionTopRight() self. SetFont(self. id.PaintDC(self) dc. The wx.Font(11.font) dc.FRAME_SHAPED | wx. we must set necessary style options. True) dc. The draw a custom image on the frame during the paint event. Linux users must install msttcorefonts package. We can They have menus.__init__(self.FONTWEIGHT_BOLD.cross. 10.bitmap.DrawBitmap(self.FONTSTYLE_NORMAL.FRAME_NO_TASKBAR prevents the self. They share lots of similarities.SIMPLE_BORDER removes application from appearing on the taskbar.ClientToScreen(event. '') app.GetPosition()) fp = (x . parent.self. I finally chose Comic Sans MS.com/wxpython/gdi/ def OnMouseMove(self. True) dc. 'Comic Sans MS') I was looking for a nice font for the note example.DrawBitmap(self. 20.delta[1]) self. 20) dc. The wx.Frame.Make a phone call'.Move(fp) def OnPaint(self. title.zetcode. 20. y = self. 0. We create a frame without a border. style=wx. 170. 20. event): if event.FRAME_SHAPED enables to create a shaped window. If we do not have a font 41 de 44 27/04/2008 1:08 . toolbars.SIMPLE_BORDER | wx.DrawText('.App() Note(None.DrawText('. This might be boring. We can wx. wx. 80) app = wx. False. wx.delta[0]. This is a proprietary font.FONTFAMILY_DEFAULT. Some developers create more fancy applications.SetTextForeground('WHITE') dc. 0.LeftIsDown(): x.Dragging() and event. event): dc = wx.MainLoop() The idea behind creating a shaped window is simple.DrawText('.font = wx. y . wx.self. the thick border. The wx. make our applications more attractive by using images. 50) dc.Go shopping'. -1.FRAME_NO_TASKBAR) In order to create a custom shaped application. Most applications are rectangular. titles etc.The Graphics Device Interface http://www. idea is as follows.Write an email'. GetWidth() h = self. wx. Linux developers wx. because def SetNoteShape(self. 0. h)) We are going to draw a bitmap on the frame.zetcode. self. The first is a rounded rectangle.Bitmap('note.bitmap.SetClientSize((w.DrawBitmap(self. illustrator to create it. self. Usually not to our taste. True) These lines are not necessary.com/wxpython/gdi/ installed.png'. It is used to close the application. The pixels outside the image become transparent.bitmap. With a kind of an orange fill. the system chooses another one.SetNoteShape) else: self. wx. For this I used Gimp image editor. The second one is a small cross.Platform == '__WXGTK__': self. we figure out the bitmap size. 42 de 44 27/04/2008 1:08 .bitmap. Then we set the site of the frame to the size of the bitmap. 0.SetShape(region) Here we set the shape of the frame to that of the bitmap. I order to cover the whole frame. *event): region = wx.bitmap) self.bitmap = wx.The Graphics Device Interface http://www.png'. because a paint event is generated during the creation of the application.EVT_WINDOW_CREATE. should call the SetNoteShape() method immediately after the dc = wx. believe. I have used Inkscape vector w = self.RegionFromBitmap(self.ClientDC(self) dc.BITMAP_TYPE_PNG) self. But we this is what I have learnt from the others. it makes the example smoother.Bind(wx. if wx.BITMAP_TYPE_PNG) I have created two bitmaps. I say we.WindowCreateEvent event.GetHeight() self.SetNoteShape() This is some platform dependent code.cross = wx.Bitmap('cross. Write an email'. 50) dc. 10.com/wxpython/gdi/ If we remove a border from the frame.DrawText('. 0] point. We intersect these two regions. 170.The Graphics Device Interface http://www.Go shopping'. dc. we cannot move the window. True) dc. 0..bitmapRegion.Offset(170.bitmapRegion. 80) Within the OnPaint() method we draw two bitmaps and three texts. self. Finally we will talk about how we close the note script.DrawBitmap(self. we close the script. This way we get all pixels that share both bitmaps.bitmapRegion.bitmap. Inside the OnLeftDown() method we check if we clicked inside 43 de 44 27/04/2008 1:08 .bitmapRegion = wx. the region.cross.RegionFromBitmap(self.GetPosition() if self. By default the region starts at [0.IntersectRegion(self. 20) dc.. 20.DrawText('.cross) self.ContainsPoint(pos): self. We use the Offset() method.zetcode. 0. The OnLeftDown() and the OnMouseMove() methods enable the user to move the window by clicking on the client area of the frame and dragging it.RegionFromBitmap(self. pos = event.crossRegion = wx.DrawText('. If true. True) dc.Close() We create two regions from two bitmaps. 10) . Finally we move the region to the point. 20. where we draw the cross bitmap.bitmap) self.DrawBitmap(self.crossRegion) self.Make a phone call'. 20. The Graphics Device Interface http://www. 2007 © 2007 Jan Bodnar 44 de 44 27/04/2008 1:08 .zetcode.Net/C#. .com/wxpython/gdi/ Figure: Note Python Purse on sale Genuine python handbags on sale We Custom Assistance Technique Java/J2ee. make handbag for you Python. Ruby eXtreme Programming Home ‡ Contents ‡ Top of Page ZetCode last modified June 3. if you can shorthen it. wx. . that will change the colour/shape of the button widget appropriately.com/wxpython/tips/ Python IDE Faster. Browser. In our case.http://www. Feel free to contact me. Ruby Tips and Tricks In this section we will show various interesting tips in elsewhere. Here we will see examples. the button the button widget with a mouse pointer.Show() i. Debugger.py 1 de 15 27/04/2008 1:09 . when we leave the area of the widget. Home Contents Easier Python Development Editor.zetcode.MainLoop() Interactive Button This tip shows how to program an interactive Button. Except for the path to the python interpreter. that could not be put The tiniest wxPython application This example is just for pure fun.EVT_LEAVE_WINDOW event is generated. Python. This button reacts to users actions. changes it's background colour.Frame(None). and more eXtreme Programming Assistance Technique Java/J2ee. wxPython.App() wx. #!/usr/bin/python # interactivebutton. #!/usr/bin/python import wx i = wx. So all you have to do is to bind those events to functions. Even for one single character. When we enter the area of wx/EVT_ENTER_WINDOW event is generated. Simirarly.Net/C#. EVT_LEAVE_WINDOW(self. The red colour catches the eye and 2 de 15 27/04/2008 1:09 . size=(-1.SetBackgroundColour( 'DARKGREY') self.com/wxpython/tips/ import wx from wx. id. event): self. parent. -1. statusbar turs red and an error message the user can easily read the error message. The following code mimics this situation.zetcode. self. self. -1 self. But wx.func) wx. 'interactivebutton. pos=(100.MainLoop() I have used a GenButton instead of a basic wx.Panel(self. 100). When a user enters an invalid command.Refresh() def func1(self.Button.btn.__init__(self.btn = GenButton(panel. A GenButton can change border settigs.http://www. 'button'.btn.EVT_ENTER_WINDOW(self.Button would work as well. title) panel = wx.btn.Frame.btn.SetBezelWidth(1) self.Refresh() app = wx. This might get annoying.Frame): def __init__(self. I have noticed a better solution in a SAP system. an error dialog usually appears.btn.SetBackgroundColour( 'GREY79') self.btn.lib.btn. event): self.buttons import GenButton class InteractiveButton(wx. -1.Show(True) def func(self. is displayed on stausbar.App() InteractiveButton(None. id.SetBackgroundColour( 'DARKGREY') wx. -1) self. parent.btn. which I find attractive.py') app.Centre() self. title): wx.func1) self. Isabelle When an error occurs in an application. http://www.zetcode.com/wxpython/tips/ Figure: Isabelle #!/usr/bin/python # Isabelle import wx ID_TIMER = 1 ID_EXIT = 2 ID_ABOUT = 3 ID_BUTTON = 4 class Isabelle(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title) self.timer = wx.Timer(self, ID_TIMER) self.blick = 0 file = wx.Menu() file.Append(ID_EXIT, '&Quit\tCtrl+Q', 'Quit Isabelle') help = wx.Menu() help.Append(ID_ABOUT, '&About', 'O Programe') menubar = wx.MenuBar() menubar.Append(file, '&File') menubar.Append(help, '&Help') self.SetMenuBar(menubar) 3 de 15 27/04/2008 1:09 http://www.zetcode.com/wxpython/tips/ toolbar = wx.ToolBar(self, -1) self.tc = wx.TextCtrl(toolbar, -1, size=(100, -1)) btn = wx.Button(toolbar, ID_BUTTON, 'Ok', size=(40, 28)) toolbar.AddControl(self.tc) toolbar.AddSeparator() toolbar.AddControl(btn) toolbar.Realize() self.SetToolBar(toolbar) self.Bind(wx.EVT_BUTTON, self.OnLaunchCommandOk, id=ID_BUTTON) self.Bind(wx.EVT_MENU, self.OnAbout, id=ID_ABOUT) self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT) self.Bind(wx.EVT_TIMER, self.OnTimer, id=ID_TIMER) self.panel = wx.Panel(self, -1, (0, 0), (500 , 300)) self.panel.SetBackgroundColour('GRAY') self.sizer=wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.panel, 1, wx.EXPAND) self.SetSizer(self.sizer) self.statusbar = self.CreateStatusBar() self.statusbar.SetStatusText('Welcome to Isabelle') self.Centre() def OnExit(self, event): dlg = wx.MessageDialog(self, 'Are you sure to quit Isabelle?', 'Please wx.NO_DEFAULT | wx.ICON_QUESTION) if dlg.ShowModal() == wx.ID_YES: self.Close(True) def OnAbout(self, event): dlg = wx.MessageDialog(self, 'Isabelle\t\n' '2004\t', 'About', wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def OnLaunchCommandOk(self, event): input = self.tc.GetValue() if input == '/bye': self.OnExit(self) elif input == '/about': self.OnAbout(self) elif input == '/bell': wx.Bell() else: self.statusbar.SetBackgroundColour('RED') self.statusbar.SetStatusText('Unknown Command') self.statusbar.Refresh() self.timer.Start(50) self.tc.Clear() def OnTimer(self, event): 4 de 15 27/04/2008 1:09 http://www.zetcode.com/wxpython/tips/ self.blick = self.blick + 1 if self.blick == 25: self.statusbar.SetBackgroundColour('#E0E2EB') self.statusbar.Refresh() self.timer.Stop() self.blick = 0 app = wx.App() Isabelle(None, -1, 'Isabelle') app.MainLoop() There is a wx.TextCtrl on the Statusbar. There you enter your commands. We have defined three commands. /bye, /about and /beep. If you mistype any of them, Statusbar turns red and displays an error. This is done with the wx.Timer class. Undo/Redo framework Many applications have the ability to undo and redo the accomplished in wxPython. user's actions. The following example shows how it can be 5 de 15 27/04/2008 1:09 http://www.zetcode.com/wxpython/tips/ Figure: undoredo.py #!/usr/bin/python # undoredo.py from wx.lib.sheet import * import wx stockUndo = [] stockRedo = [] ID_QUIT ID_UNDO ID_REDO ID_EXIT = = = = 10 11 12 13 ID_COLSIZE = 80 ID_ROWSIZE = 20 class UndoText: def __init__(self, sheet, text1, text2, row, column): self.RedoText = text2 self.row = row self.col = column self.UndoText = text1 self.sheet = sheet def undo(self): self.RedoText = self.sheet.GetCellValue(self.row, self.col) if self.UndoText == None: self.sheetSetCellValue('') else: self.sheet.SetCellValue(self.row, self.col, self.UndoText) def redo(self): if self.RedoText == None: self.sheet.SetCellValue('') else: self.sheet.SetCellValue(self.row, self.col, self.RedoText) class UndoColSize: def __init__(self, sheet, position, size): self.sheet = sheet self.pos = position self.RedoSize = size self.UndoSize = ID_COLSIZE def undo(self): self.RedoSize = self.sheet.GetColSize(self.pos) self.sheet.SetColSize(self.pos, self.UndoSize) self.sheet.ForceRefresh() 6 de 15 27/04/2008 1:09 http://www.zetcode.com/wxpython/tips/ def redo(self): self.UndoSize = ID_COLSIZE self.sheet.SetColSize(self.pos, self.RedoSize) self.sheet.ForceRefresh() class UndoRowSize: def __init__(self, sheet, position, size): self.sheet = sheet self.pos = position self.RedoSize = size self.UndoSize = ID_ROWSIZE def undo(self): self.RedoSize = self.sheet.GetRowSize(self.pos) self.sheet.SetRowSize(self.pos, self.UndoSize) self.sheet.ForceRefresh() def redo(self): self.UndoSize = ID_ROWSIZE self.sheet.SetRowSize(self.pos, self.RedoSize) self.sheet.ForceRefresh() class MySheet(CSheet): instance = 0 def __init__(self, parent): CSheet.__init__(self, parent) self.SetRowLabelAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE) self.text = '' def OnCellChange(self, event): toolbar = self.GetParent().toolbar if (toolbar.GetToolEnabled(ID_UNDO) == False): toolbar.EnableTool(ID_UNDO, True) r = event.GetRow() c = event.GetCol() text = self.GetCellValue(r, c) # self.text - text before change # text - text after change undo = UndoText(self, self.text, text, r, c) stockUndo.append(undo) if stockRedo: # this might be surprising, but it is a standard behaviour # in all spreadsheets del stockRedo[:] toolbar.EnableTool(ID_REDO, False) def OnColSize(self, event): toolbar = self.GetParent().toolbar if (toolbar.GetToolEnabled(ID_UNDO) == False): toolbar.EnableTool(ID_UNDO, True) pos = event.GetRowOrCol() size = self.GetColSize(pos) undo = UndoColSize(self, pos, size) 7 de 15 27/04/2008 1:09 id=ID_UNDO) self.toolbar. False) def OnRowSize(self.EVT_TOOL.OnUndo.EnableTool(ID_REDO.toolbar.BoxSizer(wx.NO_ wx.AddSeparator() self.toolbar.toolbar.EVT_MENU. '') self.id.parent. False) self.toolbar.Add(self. self. id=-1.EnableTool(ID_UNDO.MenuItem(menu.toolbar. self.GetParent().AddSimpleTool(ID_EXIT.Bind(wx. 'Quit'.append(undo) if stockRedo: del stockRedo[:] toolbar. ID_QUIT.Bind(wx.SetSizer(box) 8 de 15 27/04/2008 1:09 . 'Undo'.TB_FLAT | wx. border=5) box.Add((5.zetcode.TB_TEXT) self. '&Quit\tCtrl+Q'.EVT_TOOL. False) class Newt(wx.toolbar if (toolbar.append(undo) if stockRedo: del stockRedo[:] toolbar. id=ID_EXIT) box. 'Quits Newt') quit.SetBitmap(wx.VERTICAL) menuBar = wx. title.AddSimpleTool(ID_UNDO.png').http://www. '') self. wx.MenuBar() menu = wx.Bind(wx. 'Redo'.AppendItem(quit) menuBar.Bitmap('icons/exit.png').png').Bind(wx. size=(550.EVT_TOOL.SetMenuBar(menuBar) self.ToolBar(self.OnQuitNewt.Menu() quit = wx.toolbar.OnRedo.TB_HORIZONTAL | wx. False) self. pos. id=ID_QUIT) self. size) stockUndo.Frame.Bitmap('icons/redo.Bitmap('icons/undo.title): wx. wx.EnableTool(ID_UNDO.__init__(self.GetToolEnabled(ID_UNDO) == False): toolbar.EnableTool(ID_REDO.Frame): def __init__(self.com/wxpython/tips/ stockUndo.toolbar. style=wx.toolbar. self.EnableTool(ID_REDO. id=ID_REDO) self. parent.toolbar = wx. self.GetRowSize(pos) undo = UndoRowSize(self. True) pos = event.AddSimpleTool(ID_REDO.Realize() self. event): toolbar = self.10). -1. '') self.toolbar. 500)) box = wx. '&File') self.toolbar.GetRowOrCol() size = self. wx.OnQuitNewt.Append(menu.png')) menu.Bitmap('icons/exit16. 0) self. that can be redone. event): if len(stockUndo) == 0: return a = stockUndo.redo() stockUndo. event): self.sheet1.Show(True) def OnUndo(self.SetFocus() box. 'Newt') app.sheet1.SetNumberCols(25) for i in range(self.EXPAND) self. wx.Centre() self. event): if len(stockRedo) == 0: return a = stockRedo. -1. False) a.toolbar.EnableTool(ID_REDO.Close(True) app = wx. False) a.toolbar.zetcode.CreateStatusBar() self.EnableTool(ID_UNDO.GetNumberRows()): self.toolbar.MainLoop() stockUndo = [] stockRedo = [] There are two list objects. that we can undo. undo and 9 de 15 27/04/2008 1:09 .sheet1. This object has two methods. stockUndo is a list that holds all changes.EnableTool(ID_UNDO.http://www. ID_ROWSIZE) self.pop() if len(stockUndo) == 0: self.SetRowSize(i.append(a) self.sheet1 = MySheet(self) self.undo() stockRedo.com/wxpython/tips/ self.pop() if len(stockRedo) == 0: self.append(a) self. True) def OnQuitNewt(self.sheet1.App() Newt(None. True) def OnRedo(self.sheet1. 1.SetNumberRows(55) self.sheet1.EnableTool(ID_REDO. UndoText object. stockRedo keeps all changes.toolbar.Add(self. The changes are instantiated into a redo. self.ALIGN_CENTRE.EnableTool(ID_REDO. r.GetCol() text = self. self. if len(stockUndo) == 0: self. text. OpenOffice Calc works this way.text before change # text .__init__(self.text. they are aligned to the right.com/wxpython/tips/ class MySheet(CSheet): def __init__(self. wx.SetRowLabelAlignment(wx.. all redo changes are lost. Basically.toolbar. It is a grid widget with some additional logic. c) # self. self.EnableTool(ID_REDO.toolbar. r = event.ALIGN_CENTRE) Here we center the labels in rows. Gnumeric as well.GetCellValue(r. if you undo some changes and then start typing again. False) . parent): CSheet. False) Yes. an UndoText object is created and appended to the stockUndo list. By default. but it is a standard behaviour # in all spreadsheets del stockRedo[:] toolbar. c) stockUndo.append(undo) Every time we do some changes. if stockRedo: # this might be surprising. I did not know that it works this way..zetcode. parent) Our example inherits from CSheet class.http://www.EnableTool(ID_UNDO.text after change undo = UndoText(self.GetRow() c = event. this behaviour was surprising for me. until I made this example.. True) The undo and redo buttons are enabled or disabled 10 de 15 27/04/2008 1:09 .text . The location of the configuration file can be changed. This file is located in the home user directory by default. On Linux.append(a) If we click undo.undo() stockRedo. 500px. If there is no configuration file.pop() if len(stockUndo) == 0: self. We can set these values to a range from 200 the window size is set to our preffered values. After we save our values and restart the application. False) a. Users can toggle tooltips on and of. we pop up an UndoText object from the stockUndo list. #!/usr/bin/python # myconfig.py import wx class MyConfig(wx.http://www. a = stockUndo. Application settings are saved to the hard disk. If there is nothing to undo. The name of the file is specified in the constructor of the wx.Frame): 11 de 15 27/04/2008 1:09 .zetcode. change fonts. the class. Mostly they have a menu option called so that users do not have to change the settings each time the application starts. In wxPython we have wx.Config size of the window. In the following code example.Config class to do our job. settings are stored in a simple hidden file. Call the undo() method and append the object to the stockRedo list. Configuring application settings Many applications allow users to configure their settings. preferences.com/wxpython/tips/ accordingly.EnableTool(ID_UNDO. default download paths etc. the undo button is disabled. we can cofigure the height and the width of the window is set to the defaul 250 px value.toolbar. cfg. 'Save'. parent. size=(w.Frame. 15).OnSave. self.cfg. self. title): self.App() MyConfig(None. min=200. self. 'Height:'.MainLoop() Here we have the contents of a configuration file to our code example .cfg. (80. value pairs.SpinCtrl(self.StaticText(self. -1. -1.SetStatusText('Configuration saved. (60.GetValue()) self. h = self. 70)) self.cfg = wx. -1. -1). self.sc1 = wx. 65).myconfig height=230 width=350 Figure: myconfig.py') app. -1. self.com/wxpython/tips/ def __init__(self.Config('myconfig') if self.cfg.ReadInt('width').SpinCtrl(self.Button(self. -1. -1). 20)) wx. 250) wx. min=200.WriteInt("height". id=1) self.statusbar = self.Show(True) def OnSave(self.StaticText(self. str(h). 'Width:'.cfg. event): self.sc1.sc2. parent. %s ' % wx.__init__(self.Exists('width'): w. h) = (250.CreateStatusBar() self. It consists of two key. str(w). (60. id. 1.sc2 = wx.statusbar. 'myconfig. (80.EVT_BUTTON.GetValue()) self.py 12 de 15 27/04/2008 1:09 .http://www.ReadInt('height') else: (w. h)) wx. (20.WriteInt("width". $ cat . wx. title.Now()) app = wx.Centre() self.zetcode. 120)) self. id. (20.Bind(wx. (20. parent.Frame): def __init__ (self.py import wx import wx.gestures as gest class MyMouseGestures(wx. Available gestures: L for left U for up R for right D for down 7 for northwest 9 for northeast 1 for southwest 3 for southeast If you wonder why these numbers were chosen. when we do a square with a mouse pointer. Mouse gestures can be combined.Panel(self. size=(300. title): wx.MOUSE_BTN_RIGHT #!/usr/bin/python # mousegestures.lib.MouseGestures class in wxPython. -1) 13 de 15 27/04/2008 1:09 . wx.com/wxpython/tips/ Mouse gestures A mouse gesture is a way of combining computer mouse specific command. parent.__init__(self. 200)) panel = wx.Frame. id. They really Mouse gestures are created with help users save their time while browsing on the Interent. Possible flags are: wx. We can find mouse gestures in such movements and clicks which the software recognizes as a successfull applications like Firefox or Opera.gestures.zetcode. This wx.MOUSE_BTN_LEFT at the numerical pad.lib.MOUSE_BTN_MIDDLE wx. title. id. have a look way 'RDLU' is a mouse gesture triggered.http://www. py') app. 2) mg. self.MouseGestures(panel.com/wxpython/tips/ mg = gest. False for manual. Last parameter defines a mg. which will be pressed when triggering gestures.OnDownRight) We register a mouse gesture with the AddGesture() method. are happy with the automatic way. Manual is not fully implemented and we mouse button.zetcode. The button can be later changed with the SetMouseButton() method.Show(True) def OnDownRight(self): self. 0. 0. self.SetGesturePen(wx. we have registered a mouse gesture for a panel. we have to create a MouseGesture object. The first parameter is a window.SetGesturesVisible(True) We set this gesture visible with the SetGesturesVisible() method. pressed and we go down and right with a cursor. where the mouse gesture is registered.Centre() self. 0). True.MOUSE_BTN_LEFT) If we want to use mouse gestures. 14 de 15 27/04/2008 1:09 .MainLoop() In our example. They will be 2 pixels wide. mg.AddGesture('DR'.AddGesture('DR'. As in letter mg = gest.OnDownRight) self. 'mousegestures.MouseGestures(panel. when a left button is 'L'.SetGesturePen(wx. 0).SetGesturesVisible(True) mg.App() MyMouseGestures(None. wx. True is for automatic.Colour(255. wx. Our mouse gesture will close the application. 2) Our gestures will be painted as red lines. Second parameter defines a way to register a gesture. -1.Close() app = wx.http://www.MOUSE_BTN_LEFT) mg. True. mg.Colour(255. Mouse gesture is triggered. solowest. Python Purse on sale Genuine python handbags on sale We Custom make handbag for you www.com/wxpython/tips/ The first parameter is the gesture.com TT-Solutions wxWidgets (wxWindows) consulting and development.http://www.zetcode. Second parameter is the method triggered by the gesture.com Home ‡ Contents ‡ Top of Page ZetCode last modified July 10. Ask the wxExperts! www. 2007 © 2007 Jan Bodnar 15 de 15 27/04/2008 1:09 .tt-solutions. id. There is a long. These graphical scripts or "gripts" will demonstrate various areas in programming. title. title): wx.Dialog. Short and easily remembered. Browser. 420)) panel = wx. Figure: Tom #!/usr/bin/python # Tom import wx import smtplib class Tom(wx. But it is still a laborious task.Panel(self. size=(400. Easier Python Development Editor. complete scripts. parent. Tom Each application should have a good name.__init__(self.zetcode. and more www. So.wxPython gripts http://www.com Python IDE wxPython Gripts In this section we will show some small. we have Tom. -1) 1 de 12 27/04/2008 1:09 .Dialog): def __init__(self. wxPython is easier than in most other toolkits. A simple gript that sends an email.wingware. Debugger. Programming in Python. id. long way from easy scripts to professional applications. parent.com/wxpython/gripts/ Home Contents Faster. SMTP('mail.write = wx.Add(hbox1.Bind(wx.BOTTOM.com/wxpython/gripts/ self.BoxSizer(wx.ICON_ERROR) dlg. 'Failed to send email'.BoxSizer(wx. style=wx.VERTICAL) hbox1 = wx.tc1. 10) vbox.tc2 = wx.ShowModal() self.Add(st2.HORIZONTAL) hbox3 = wx. 'Send') hbox1. event): sender = self. 15) vbox. -1.LEFT.Add(hbox2. -1.ShowModal() dlg. 10) vbox.StaticText(panel. -1.TextCtrl(panel.Add(st1. wx.tc2.ICON_INFORMATION) dlg. 10) hbox3.GetValue() subject = self. wx. -1.write. 0.OK | wx.Add(hbox3.LEFT.TOP. wx. 0. recipient. recipient.TextCtrl(panel. -1)) self.GetValue() header = 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n' % (sender.App() Tom(None.GetValue() recipient = self.StaticText(panel.Destroy() app = wx. size=(180. wx.LEFT.TE_MULTILINE) button_send = wx.Destroy() except smtplib. 2 de 12 27/04/2008 1:09 . 'Error'.Button(panel.BoxSizer(wx. wx.HORIZONTAL) st1 = wx. wx. 35) hbox2.tc1 = wx. 0.LEFT.HORIZONTAL) hbox2 = wx. 20) self.RIGHT | wx.StaticText(panel.chello. message) server.tc2. 0.Add(st3.TOP. This module is part of the python language. 0.quit() dlg = wx. self.GetValue() text = self.write.Add(self.LEFT.MessageDialog(self.TextCtrl(panel. -1.MainLoop() For working with emails we need to import smtp module.OnSend. -1.SetSizer(vbox) self. 10) hbox2. 10) vbox. 'Success'. wx. 0. 'Email was successfully sent'.Add(button_send. wx. 10) hbox1.BoxSizer(wx. error: dlg = wx. 'Subject') http://www.ShowModal() dlg. size=(180. 'From') st2 = wx. 0.tc3. 0.tc1.TOP.tc3. 0.TOP | wx.sendmail(sender.tc3 = wx. wx.TOP | wx. 1. -1.Add(self.LEFT.EVT_BUTTON.EXPAND | wx.Add(self.OK | wx.LEFT. 50) hbox3.TextCtrl(panel.sk') server. wx. -1)) self.Add(self.ALIGN_CENTER | wx. -1.MessageDialog(self. size=(180. wx.Centre() self.Destroy() def OnSend(self. 'To ') st3 = wx. subject) message = header + text try: server = smtplib. 0. 'Tom') app. 1. wx. -1)) self.SMTPException. id=1) panel.zetcode. 20) vbox.wxPython gripts vbox = wx. wx. method. So header = 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n' % (sender. subject) Next we create an SMTP connection. Each ISP gives you the name of the pop and smtp servers. recipient.chello.sk') server. newline as shown here.chello. 'mail.com/wxpython/gripts/ import smtplib From.sendmail(sender. Here you specify your settings. In my case. Finally. we quit the connection with the quit() method. message) server. A mail is sent by calling the sendmail() server = smtplib.sk' is a name for both.quit() Editor This editor example is the largest so far.wxPython gripts http://www. recipient.SMTP('mail. To and Subject options must be separated by carriedge return and we must follow it. This weird thing is requested by RFC 821 norm.zetcode. Figure: Editor #!/usr/bin/python # Editor import wx import os 3 de 12 27/04/2008 1:09 . png')) file.MenuItem(file.AppendItem(about) menubar. 105.Bitmap('icons/stock_open-16.SetBitmap(wx.Bitmap('icons/stock_save-16. 'Quit the Application') quit. title.\tShift+Ctrl+S'. parent.Bitmap('icons/stock_delete-16.Bitmap('icons/stock_cut-16.MenuItem(file.SetBitmap(wx.AppendItem(open) file. 'Select &All\tCtrl+A'.AppendItem(copy) paste = wx. '&Statusbar'. 'Delete the selected text') delete. 'Save the file with a different name') saveas. 'Open an existing file') open. 112.png')) help.MenuItem(edit. '&Copy\tCtrl+C'. '&About\tF1'. '&Delete'.MenuItem(file.MenuItem(edit.Append(111. '&Quit\tCtrl+Q'.)) edit.MenuBar() file = wx.AppendItem(new) open = wx.zetcode. 101. 'Paste text from clipboard') paste.Menu() about = wx.png')) file.MenuItem(file.Menu() new = wx. 'Copy the Selection') copy.png'.MenuItem(edit. title): wx. 102.png')) edit. 'Cut the Selection') cut.Menu() view.SetBitmap(wx. 'About Editor') about.Bitmap('icons/stock_new-16.SetBitmap(wx.Frame.Bitmap('icons/stock_copy-16.png')) file. '&Cut\tCtrl+X'.wxPython gripts http://www.SetBitmap(wx.Bitmap('icons/stock_exit-16.MenuItem(edit. id. 104.AppendSeparator() quit = wx.modify = False self.Bitmap('icons/stock_paste-16.AppendItem(saveas) file.. 107. 'Save &As.AppendSeparator() edit.AppendItem(quit) edit = wx. 108.Frame): def __init__(self.last_name_saved = '' self.png')) edit. 106.MenuItem(file. id. parent.png')) file.png')) file. '&Edit') 4 de 12 27/04/2008 1:09 .png')) edit.Append(file..Append(edit. 'Save the file') save.Menu() cut = wx. '&Save\tCtrl+S'.replace = False # setting up menubar menubar = wx.AppendItem(save) saveas = wx. size=(600. 'Show StatusBar') help = wx.AppendItem(delete) edit.__init__(self. '&New\tCtrl+N'.SetBitmap(wx. 103.SetBitmap(wx.SetBitmap(wx.Bitmap('icons/stock_save_as-16.com/wxpython/gripts/ class Editor(wx.Bitmap('icons/stock_about-16. '&File') menubar. 'Select the entire text') view = wx.SetBitmap(wx.AppendSeparator() save = wx. 500)) # variables self. 'Creates a new document') new.SetBitmap(wx. '&Paste\tCtrl+V'.AppendItem(cut) copy = wx.Append(110.MenuItem(help.AppendItem(paste) delete = wx. '&Open\tCtrl+O'. 109. OnOpenFile. 1000. self. id=107) self. self.OnCut.toolbar.toolbar = self.AddSeparator() self. self. self.toolbar.Bind(wx.Bind(wx. id=803) self. self. id=108) self.AddSimpleTool(802.EVT_MENU. id=101) self.CANCEL | wx.EVT_MENU.TextCtrl(self. wx.png').YES_NO | wx.ToggleStatusBar.wxPython gripts menubar.OnKeyDown) self.EVT_TEXT.Bind(wx.EVT_MENU.TE_MULTILINE | wx.Bitmap('icons/stock_exit.Bind(wx. 'Exit'.text. 'Copy'. wx.OnSaveAsFile.com/wxpython/gripts/ self. id=103) self.NO_BORDER | wx.OnSaveFile.QuitApplication.png'). self. wx.ShowModal() if val == wx.modify: dlg = wx.Realize() self. self. self.Bind(wx.EVT_MENU. id=106) self. id=806) self.AddSimpleTool(801.toolbar.EVT_TOOL.OnPaste. event): file_name = os.Bind(wx. id=105) self.CreateToolBar( wx.Bind(wx.EVT_KEY_DOWN. self.png').AddSeparator() self. wx. '&View') menubar.png'). self.path.OnAbout.TE_PROCESS_ENTER) self. wx.AddSimpleTool(804. wx.OnSelectAll.Bind(wx.Bind(wx.OnPaste. self.SetFocus() self. id=801) self.text. id=104) self.Append(help.EVT_MENU.EVT_TOOL. size=(-1.TB_HORIZONTAL | wx.zetcode.EVT_MENU. id=111) self.AddSimpleTool(803.Show(True) def NewApplication(self. 'New'. wx.OnSaveFile.png').Bitmap('icons/stock_new.EVT_MENU. self. self. '') self.SetMenuBar(menubar) self.Bind(wx. '') self. self.basename(self.OnDelete. 'Paste'.Bind(wx. style=wx.toolbar. 'Cut'.Bind(wx. event): editor = Editor(None.AddSimpleTool(806.toolbar. id=112) # setting up toolbar self.ID_YES: self.QuitApplication.toolbar.toolbar.TB_TEXT ) self. 'Save'.EVT_MENU.EVT_MENU.Bitmap('icons/stock_paste.OnTextChanged.OnOpenFile. self.Bitmap('icons/stock_copy.EVT_MENU.TB_FLAT | wx. id=805) self.OnCopy.EVT_TOOL. self. self. '') self.Bitmap('icons/stock_save.Bind(wx.OnSaveFile(event) 5 de 12 27/04/2008 1:09 . http://www.NewApplication.QuitApplication) self.png'). '') self.png').NewApplication.Bind(wx.Centre() self. '') self. self.EVT_TOOL. self.Bind(wx. 'Open'.Bind(wx. id=110) self. id=109) self.EVT_MENU.Bind(wx. id=807) self. id=102) self.EVT_TOOL. self.Show() def OnOpenFile(self.StatusBar() self.text. ''.MessageDialog(self.text = wx.EVT_TOOL.Bind(wx.Bitmap('icons/stock_open.YES_DEFAULT | wx.Bitmap('icons/stock_cut. 'Editor') editor. '&Help') self. id=804) self.OnCopy.Bind(wx.EVT_MENU.AddSimpleTool(805.toolbar. '') self.toolbar. wx.ICON_QUESTION) val = dlg.EVT_TOOL.EVT_CLOSE.Append(view.Bind(wx.toolbar. id=802) self. -1). ''. -1.last_name_saved) if self.OnCut. 'Save changes?'. self.Centre() editor. '') self.Bind(wx. id=1000) self.Bind(wx.AddSimpleTool(807. . 'w') text = self. defaultFile='' wildcard=wcd.CHANGE_DIR) if open_dlg.DoOpenFile() elif val == wx.MessageDialog(self.close() self.MessageDialog(self.ef)|*.ShowModal() else: self.FileDialog(self.ef|' dir = os. defaultFile=''.GetLastPosition(): self.text.ef)|*.WriteText(text) self.ShowModal() open_dlg.SetStatusText(''.text.OVERWRITE_PROMPT) if save_dlg.SetStatusText(''.basename(self.ShowModal() == wx. message='Save file as.statusbar.ID_OK: path = open_dlg. 'r') text = file.SetStatusText(os.OPEN|wx.write(text) file.modify = False self. 'Error opening file\n' + str(error)) dlg.ID_CANCEL: dlg.text.write(text) 6 de 12 27/04/2008 1:09 ..getcwd() save_dlg = wx.read() file.text.Destroy() def OnSaveFile(self.last_name_saved = path self. defaultDir=dir.ID_OK: path = save_dlg. event): if self.text.ef|' dir = os. 1) except IOError. error: dlg = wx.getcwd() open_dlg = wx. 'w') text = self.close() if self.FileDialog(self.GetPath() try: file = open(path. 1) self. 'Error saving file\n' + str(error)) dlg.Clear() self. self.ShowModal() == wx.Destroy() else: self. event): wcd='All files(*)|*|Editor files (*.DoOpenFile() http://www. 'Error opening file\n' + str(error)) dlg. message='Choose a file'. wildcard=wcd.ShowModal() except UnicodeDecodeError.OnSaveAsFile(event) def OnSaveAsFile(self.GetValue() file.SAVE | wx.MessageDialog(self.modify = False except IOError. defaultDir=dir.zetcode.com/wxpython/gripts/ def DoOpenFile(self): wcd = 'All files (*)|*|Editor files (*.GetPath() try: file = open(path.path. error: dlg = wx.wxPython gripts self.last_name_saved) + ' saved'.DoOpenFile() else: self.last_name_saved.last_name_saved: try: file = open(self.'. error: dlg = wx.statusbar.GetValue() file.statusbar. style=wx. style=wx. Destroy() def OnDelete(self.com/wxpython/gripts/ file.text.replace = False event.statusbar.modify: wx.statusbar. event): self. event): self. 2) self.zetcode.modify: dlg = wx.path. to) def OnSelectAll(self.statusbar. event): frm.text. 'Error saving file\n' + str(error)) dlg.ShowModal() save_dlg.replace = True else: self.YES_NO | wx.Remove(frm. 1) event.Exit() elif val == wx. to = self.Skip() def ToggleStatusBar(self. event): self.close() self.Show() def StatusBar(self): self.Hide() else: self.last_name_saved = os.MessageDialog(self.YES_DEFAULT | wx.MessageDialog(self.Skip() def OnKeyDown(self.replace: self.statusbar.GetSelection() self.modify = False self.SetStatusText('INS'. 'Save before Exit?'.SetStatusText(''.basename(path) self. event): self.Copy() def OnPaste(self.SetStatusText(self.ID_YES: self.Destroy() def OnCut(self. ''. error: dlg = wx.GetKeyCode() if keycode == wx.SetStatusText(' modified'.statusbar = self. event): if self.OnSaveFile(event) if not self.Destroy() else: self. 2) self.statusbar. 0) self. wx.SelectAll() def OnTextChanged(self.statusbar.Destroy() else: self. event): self.statusbar.text.last_name_saved + ' saved'.IsShown(): self.WXK_INSERT: if not self.Cut() def OnCopy(self.SetStatusText(''.modify = True self. event): if self.ICON_QUESTION) val = dlg.wxPython gripts http://www.CreateStatusBar() 7 de 12 27/04/2008 1:09 .text.CANCEL | wx.statusbar.ShowModal() if val == wx. 1) except IOError.text.Paste() def QuitApplication(self.ID_CANCEL: dlg. event): keycode = event.text. EVT_SIZE. Kika shows a connected icon on the statusbar.zetcode. If a login is successfull. -1. self. 0) self. a disconnected icon is do not have an ftp account. parent): wx.OK | wx. -1]) http://www.ICON_INFORMATION) dlg.StaticBitmap(self. -2. -2]) self.App() Editor(None. If you Figure: Kika #!/usr/bin/python # kika.SetStatusWidths([-5.Bind(wx.statusbar.py from ftplib import FTP.SetFieldsCount(3) self.__init__(self.MessageDialog(self.MainLoop() Kika Kika is a gript that connects to an ftp site.statusbar. parent) self.SetStatusText('Welcome to Kika'. Otherwise. -1.StatusBar. you can try to login to some anonymous ftp sites.OnSize) 8 de 12 27/04/2008 1:09 . wx.wxPython gripts self.SetFieldsCount(2) self. '\tEditor\t\n Another Tutorial\njan bodnar 2005-2006'.com/wxpython/gripts/ def OnAbout(self.Bitmap('icons/disconnected.Destroy() app = wx. 'Editor') app.png')) self. event): dlg = wx. wx. displayed. 'About Editor'.SetStatusWidths([-5. We use an ftplib module from the python standard library.StatusBar): def __init__(self.icon = wx.ShowModal() dlg. all_errors import wx class MyStatusBar(wx. -1)) self.ftpsite.statusbar = MyStatusBar(self) self.GetValue() login = self. 'Connect'. (120.Bitmap('icons/connected.password = wx.App() Kika(None.statusbar.GetValue() try: self.ftp = None con = wx.login(login. password) self. event): self.SetStatusText('Incorrect params') self. 'DisConnect'.Frame): def __init__(self.wxPython gripts self.ftpsite = wx.ftp = None except all_errors. event): if not self.Button(self. ''. (10.Frame. 2.ftp: ftpsite = self. 95).statusbar. -1. 60)) wx. self. style=wx.PlaceIcon() http://www.statusbar.SetStatusText('User connected') self.TextCtrl(self.statusbar) self. -1. 'Kika') app. id.Centre() self.__init__(self.Bind(wx. err: self.TextCtrl(self.SetPosition((rect.zetcode.GetValue() password = self. self.login. (120. id=1) self. -1. 55).login = wx.ftp = FTP(ftpsite) var = self.SetForegroundColour(wx.StaticText(self.TextCtrl(self.icon.Bitmap('icons/disconnected.SetBitmap(wx. ''.y+3)) def OnSize(self.StaticText(self. (10.password.quit() self.x+3. 15). 'Ftp site'. -1)) self.ftp: self.OnConnect. 270)) wx. 20)) wx. parent.Button(self.ftp = None def OnDisConnect(self.ftp. 'Password'. title): wx. -1.SetStatusText(str(err)) self.TE_PASSWORD) self.EVT_BUTTON.SetBitmap(wx. 100)) self. parent. size=(250. 1.icon. (10.MainLoop() 9 de 12 27/04/2008 1:09 . id=2) self.SetStatusText('User disconnected') self. -1.icon.Show() def OnConnect(self.ftp. ''. event): if self. title.statusbar. 160)) self. 160)) discon = wx. -1). (120.PlaceIcon() def PlaceIcon(self): rect = self. -1. id.Bind(wx.png')) except AttributeError: self.png')) app = wx.SetStatusBar(self.ftp = None self.statusbar. rect.statusbar.EVT_BUTTON.com/wxpython/gripts/ class Kika(wx. -1. (110.OnDisConnect. 'Login'.RED) self. (110. (110.GetFieldRect(1) self. (10. (120.StaticText(self.statusbar. 0) numbers = [0. rect.sizer = wx. id. character from the Ice Age movie.Bind(wx.__init__(self.Dialog): def __init__(self. we must position our icon to a new place. 2].GridSizer(3.jpg'. we introduce a puzzle game. It is cut into 9 pieces and shuffled.SetPosition((rect. [3. title): wx. 'images/seven. 'images/five.zetcode.x+3. The Figure: Puzzle #!/usr/bin/python # puzzle. 0. 'images/eight. 'images/three. 1.jpg'. 7.jpg'. id=button. self.Bitmap(images[i])) button. 4.py import wx import random class Puzzle(wx. 4. 6. 8] ] self.GetId()) 10 de 12 27/04/2008 1:09 .jpg'. title) images = ['images/one.OnPressButton.wxPython gripts http://www. [6. We have an image of a Sid goal is to form the picture. 2.pos = [ [0. 'images/four.icon.shuffle(numbers) for i in numbers: button = wx.BitmapButton(self.jpg'. 1. 'images/two.EVT_BUTTON. wx. 5].jpg'.jpg'.Dialog. 3. 'images/six. def PlaceIcon(self): rect = self.GetFieldRect(1) self. i. 3.y+3)) Puzzle In this gript. id. 5.com/wxpython/gripts/ Notice that each time the window is resized. parent.jpg'] self. 7] random. parent. jpg'.panel.App() Puzzle(None.sizer.panel) self.panel) self. button) self.y panelX = self.jpg'.GetPosition().Centre() self.sizer. 'Puzzle') app.jpg'. 'images/three.Remove(button) self.x buttonY = button.panel) self.sizer.GetSize().com/wxpython/gripts/ self. 'images/four.Remove(self.Remove(self.Remove(button) self.zetcode.sizer. 'images/five.Remove(button) self. 'images/seven. Each part of the picture is placed on one button widget.buttonX) == sizeX: self.panel. 'images/eight.GetPosition().panel) self. self.Insert(buttonIndex+1.Layout() app = wx.sizer.sizer.panel = wx.Layout() if (buttonX == panelX) and (panelY .pos[buttonPosY][buttonPosX] if (buttonX == panelX) and (panelY . button) self.sizer.Insert(buttonIndex.GetEventObject() sizeX = self. 82)) self.sizer.Destroy() def OnPressButton(self. -1.sizer.Remove(button) self.Add(self.panel) self.buttonX) == -sizeX: self.sizer.sizer.sizer.panel. button) self.jpg'] The picture was cut into 9 parts of 100x70 size.GetPosition(). button) self.sizer.sizer.Add(button) http://www.panel) self.x panelY = self.wxPython gripts self.y buttonX = button.sizer.Layout() if (buttonY == panelY) and (panelX . self. program. -1.MainLoop() images = ['images/one.jpg'. size=(112.sizer.panel) self.sizer.sizer. 'images/six. I did it with the Gimp one.x sizeY = self. self.jpg'.sizer.Insert(buttonIndex.Remove(self.sizer. self. Except 11 de 12 27/04/2008 1:09 .jpg'.buttonY) == -sizeY: self.Insert(buttonIndex.panel) self.Button(self.jpg'.Insert(buttonIndex-3.panel) self.Insert(buttonIndex. event): button = event. 'images/two.sizer) self.SetSizerAndFit(self.sizer.ShowModal() self.Layout() if (buttonY == panelY) and (panelX .Insert(buttonIndex-1.sizer.Remove(self.Insert(buttonIndex+3.y buttonPosX = buttonX / sizeX buttonPosY = buttonY / sizeY buttonIndex = self.buttonY) == sizeY: self.panel.GetPosition().GetSize(). sizer = wx. 82)) self. 2. 5. It is the 'travelling' button. 6.GridSizer(3.Button(self. 1. 0. Those numbers are shuffled so that we have a order of bitmaps.shuffle(numbers) We have eight numbers.panel) This button has no bitmap.Add(self. 2007 © 2007 Jan Bodnar 12 de 12 27/04/2008 1:09 . Ruby on Rails Development for business critical solutions backed by a fully managed service Python Purse on sale Genuine python handbags on sale We Custom make handbag for you Home ‡ Contents ‡ Top of Page ZetCode last modified June 3. 4. -1. we will have a different self. size=(112. It always exchanges it's position with the hitted button.wxPython gripts http://www.GridSizer fits ideally. 3. 3. numbers = [0. random number order. wx. 0) For this gript. Each time we start the gript.sizer.zetcode. 7] random.panel = wx.com/wxpython/gripts/ self. we have seven different shapes called tetrominoes. T-shape.zetcode. Download Play Contents Now Free . The original game was designed and programmed by a russian programmer Alexey Pajitnov in 1985. Even my mobile phone has a modified version of the tetris game. We use wx. S-shape.Free Juegos Tetris 100% Gratis The Tetris game in wxPython Tetris The tetris game is one of the most popular computer games ever created. L-shape.Timer to create a game cycle 1 de 12 27/04/2008 1:10 . MirroredL-shape and a Square-shape. tetris is Más de 1000 juegos para descargar Ningún available on almost every computer platform in lots of variations. Since then. Z-shape. wxPython and other application toolkits can be used to The development We do not have images for our tetris game. If we manage to form a row. Nevertheless. Line-shape. The shapes are falling down the board. create games. the row is destroyed and we score.com/wxpython/thetetrisgame/ HomeThe Official Monopoly Game. toolkit. The object of the tetris game is to move and rotate the shapes. Tetris is called a falling block puzzle game. Behind every computer game. Each of these shapes is formed with four squares. we draw the tetrominoes using the drawing API available in the wxPython programming So it is in tetris. We play the tetris game until we top out.Play Anytime! Play Monopoly . there is a mathematical model.The Tetris game in wxPython http://www. In this game. There are other libraries which are targeted at creating computer games. Figure: Tetrominoes wxPython is a toolkit designed to create applications. Some ideas behind the game. so that they fit as much as possible. ID_TIMER) self.Panel.EVT_PAINT.EVT_TIMER. id=Board.board.board = [] self. parent.board = Board(self) self.statusbar = self.Show(True) class Board(wx. Board.curY = 0 self.curX = 0 self. id.curPiece = Shape() self. parent. self.Timer(self.SetStatusText('0') self.zetcode.timer = wx.isWaitingAfterLine = False self. title.ID_TIMER) self.board.com/wxpython/thetetrisgame/ The shapes move on a square by square basis (not pixel by Mathematically a board is a simple list of numbers The following example is a modified version of the tetris game.OnPaint) self.__init__(self.start() self.Panel): BoardWidth = 10 BoardHeight = 22 Speed = 300 ID_TIMER = 1 def __init__(self.OnTimer.py import wx import random class Tetris(wx. self.Bind(wx. size=(180.OnKeyDown) self. 380)) self. parent) self.nextPiece = Shape() self.isStarted = False self. id.clearBoard() def shapeAt(self.statusbar.isPaused = False self.Centre() self. title): wx.numLinesRemoved = 0 self.SetFocus() self.Bind(wx. available with PyQt4 installation files. self.__init__(self.Frame. y): 2 de 12 27/04/2008 1:10 . #!/usr/bin/python # tetris.The Tetris game in wxPython The tetrominoes are drawn pixel) http://www. parent): wx.CreateStatusBar() self.EVT_KEY_DOWN.Bind(wx.Frame): def __init__(self. x. clearBoard() self.drawSquare(dc. x.curY . shape) if self.board[(y * Board.isPaused: return self.board.i . event): dc = wx.append(Tetrominoes.BoardHeight * Board.timer.isPaused: self.numLinesRemoved)) self.SetStatusText('paused') else: self.board[(y * Board.zetcode.isPaused statusbar = self.shape() != Tetrominoes.statusbar if self. shape): self.GetHeight() .GetClientSize() boardTop = size.Refresh() def clearBoard(self): for i in range(Board.NoShape: for i in range(4): x = self.curPiece.curPiece.isStarted: return self.numLinesRemoved = 0 self.BoardWidth): shape = self.NoShape: self.1) if shape != Tetrominoes.shapeAt(j. 0 + j * self.squareWidth().timer.GetClientSize(). Board. y.The Tetris game in wxPython http://www.NoShape) def OnPaint(self.GetParent().x(i) y = self.BoardHeight def start(self): if self.Start(Board.Start(Board.GetHeight() / Board.isStarted = True self.timer.BoardWidth def squareHeight(self): return self.BoardWidth) + x] def setShapeAt(self.curPiece.GetClientSize().SetStatusText(str(self.newPiece() self.BoardHeight .isPaused = not self.isWaitingAfterLine = False self.BoardWidth): self.BoardHeight): for j in range(Board.Speed) statusbar.BoardHeight * self.squareHeight(). boardTop + i * self.Speed) def pause(self): if not self.y(i) 3 de 12 27/04/2008 1:10 .BoardWidth) + x] = shape def squareWidth(self): return self.Stop() statusbar.PaintDC(self) size = self.curX + self.com/wxpython/thetetrisgame/ return self.Board.self.squareHeight() for i in range(Board.GetWidth() / Board. curY) elif keycode == wx.curPiece. self.curPiece. event): if not self.isPaused: return elif keycode == wx. self.1): self.rotatedLeft(). self. self.y(i) 4 de 12 27/04/2008 1:10 .curPiece.shape()) def OnKeyDown(self.y .GetKeyCode() if keycode == ord('P') or keycode == ord('p'): self.curPiece.NoShape: event.squareHeight().Skip() return keycode = event.tryMove(self.self.curPiece.dropDown() elif keycode == ord('D') or keycode == ord('d'): self.tryMove(self.curX + self.rotatedRight().curPiece. self.curX + 1. self.The Tetris game in wxPython http://www.oneLineDown() else: event.curY .curY .tryMove(self. self.curPiece. 0 + x * self.curY while newY > 0: if not self.curX. newY .com/wxpython/thetetrisgame/ self.ID_TIMER: if self.tryMove(self.shape() == Tetrominoes.WXK_UP: self. event): if event.curPiece.curY) elif keycode == wx.oneLineDown() else: event.isWaitingAfterLine = False self.pause() return if self.GetId() == Board.pieceDropped() def oneLineDown(self): if not self.BoardHeight .WXK_LEFT: self.x(i) y = self.WXK_RIGHT: self.Skip() def OnTimer(self.squareWidth().curPiece.pieceDropped() def pieceDropped(self): for i in range(4): x = self.curX.1) * self.drawSquare(dc.1): break newY -= 1 self.tryMove(self.Skip() def dropDown(self): newY = self. boardTop + (Board. self.isWaitingAfterLine: self. self. self.curY) elif keycode == wx.curY) elif keycode == wx.curX.isStarted or self.curX.zetcode. self.newPiece() else: self.WXK_SPACE: self.1.curPiece.tryMove(self.WXK_DOWN: self. self.curX . removeFullLines() if not self.minY() if not self.Refresh() def newPiece(self): self. self.curPiece = self.newPiece.setShape(Tetrominoes.The Tetris game in wxPython http://www. newY): for i in range(4): x = newX + newPiece.curY = Board.curPiece.GetParent().curX = Board. k.BoardHeight: return False if self.numLinesRemoved + numFullLines statusbar.NoShape) self.newPiece() def removeFullLines(self): numFullLines = 0 statusbar = self.curPiece.1 + self.setRandomShape() self.nextPiece statusbar = self.append(i) rowsToRemove.Stop() self. y) != Tetrominoes.BoardWidth or y < 0 or y >= Board.BoardHeight .setShapeAt(x.SetStatusText('Game over') def tryMove(self.curY): self.statusbar self.x(i) y = newY .BoardHeight): for l in range(Board. self. Board.reverse() for m in rowsToRemove: for k in range(m.BoardHeight): n = 0 for j in range(Board.BoardWidth): self. newPiece.NoShape: n = n + 1 if n == 10: rowsToRemove.isWaitingAfterLine = True self.y(i) if x < 0 or x >= Board.isWaitingAfterLine: self. newX.shapeAt(j.curPiece.nextPiece.BoardWidth / 2 + 1 self.timer. self.curX.GetParent().curPiece.shapeAt(x.zetcode.tryMove(self.com/wxpython/thetetrisgame/ self.numLinesRemoved = self.statusbar rowsToRemove = [] for i in range(Board.setShape(Tetrominoes. k + 1)) numFullLines = numFullLines + len(rowsToRemove) if numFullLines > 0: self. y.shapeAt(l.numLinesRemoved)) self.shape()) self.NoShape) self.setShapeAt(l.NoShape: return False 5 de 12 27/04/2008 1:10 . i) == Tetrominoes. self.isStarted = False statusbar.curPiece.BoardWidth): if not self.SetStatusText(str(self. Refresh() return True def drawSquare(self. '#3B803B'.squareHeight() .TRANSPARENT_PEN) dc. '#FC79FC'. 0). '#66CCCC'. 1)) 6 de 12 27/04/2008 1:10 . y + 1) dc.squareHeight() . self. 0).1. 1)). '#803B80'. 0). -1).zetcode. x. (0. 1). dc. '#FCC600'] dark = ['#000000'. (1. 2)). x + self. ((0. (0. (-1. '#CC6666'. '#6666CC'. '#3B8080'. 1)). '#3B3B80'. '#80803B'.2. y) darkpen = wx. 1). '#806200'] pen = wx.1) dc. 1)).curX = newX self. -1). ((1. self.SetCap(wx. 1)). '#CC66CC'. 0). -1).DrawLine(x. y) dc. (0. 0). (-1.squareHeight() . (0. '#803C3B'. ((0. 0).SetBrush(wx. (0.2) class Tetrominoes(object): NoShape = 0 ZShape = 1 SShape = 2 LineShape = 3 TShape = 4 SquareShape = 5 LShape = 6 MirroredLShape = 7 class Shape(object): coordsTable = ( ((0. 0). ((0. 1)).SetPen(darkpen) dc. '#7979FC'. (0. (0.DrawLine(x + 1.SetPen(wx. '#FCFC79'. y + self.DrawLine(x.squareWidth() .squareWidth() . 0). ((-1. '#79FC79'. ((0. -1). (0.Pen(dark[shape]) darkpen. y.Pen(light[shape]) pen.squareHeight() .squareWidth() . 0). ) (0. ((-1.SetCap(wx. x. 0). y + self. 0). (0.squareWidth() .1. (1. (1. '#66CC66'.CAP_PROJECTING) dc. (1. (1. 0)). '#CCCC66'. x + self. (0.1. (0. '#DAAA00'] light = ['#000000'. (0. -1).DrawLine(x + self. y + 1. 0).1. y + self.1. x + self.squareWidth() .DrawRectangle(x + 1. -1). shape): colors = ['#000000'.curY = newY self. (0. y + self.squareHeight() . (0.The Tetris game in wxPython http://www.CAP_PROJECTING) dc. 0). 0). -1). (0.1.com/wxpython/thetetrisgame/ self. '#F89FAB'.Brush(colors[shape])) dc. y.1. '#79FCFC'.SetPen(pen) dc. 0). (0.curPiece = newPiece self. coords[0][1] for i in range(4): m = max(m.setShape(Tetrominoes.coords[0][1] for i in range(4): m = min(m. index.randint(1.coords[0][0] for i in range(4): m = max(m.NoShape) def shape(self): return self. 7)) def x(self.pieceShape def setShape(self. index. shape): table = Shape.coords[i][0]) return m def minY(self): m = self. self.coordsTable[shape] for i in range(4): for j in range(2): self. self.coords[i][0]) return m def maxX(self): m = self.coords[index][1] def setX(self. index): return self. index): return self.zetcode.coords = [[0. self.coords[i][1]) return m def rotatedLeft(self): 7 de 12 27/04/2008 1:10 .com/wxpython/thetetrisgame/ def __init__(self): self.coords[i][1]) return m def maxY(self): m = self.coords[index][0] = x def setY(self.coords[i][j] = table[i][j] self. self.NoShape self.coords[index][0] def y(self.coords[index][1] = y def minX(self): m = self.setShape(random.pieceShape = Tetrominoes. x): self.The Tetris game in wxPython http://www.pieceShape = shape def setRandomShape(self): self.0] for i in range(4)] self.coords[0][0] for i in range(4): m = min(m. y): self. pieceShape for i in range(4): result.y(i)) result. no acceleration is implemented.SquareShape: return self result = Shape() result.curX = 0 self. We can pause the game by pressing the p key.numLinesRemoved = 0 self. Board. The d key will drop the piece one line down. -1.BoardHeight): for j in range(Board.setY(i. (It can be used to speed up the falling a bit. 'Tetris') app. so that it is easier to understand. self..com/wxpython/thetetrisgame/ if self.x(i)) return result def rotatedRight(self): if self. The game starts immediately. -self. self.i .. after it is launched. 7.pieceShape = self.x(i)) return result app = wx.curY = 0 self.y(i)) result.pieceShape for i in range(4): result.App() Tetris(None.1) if shape != Tetrominoes.pieceShape == Tetrominoes.SquareShape: return self result = Shape() result.BoardWidth): shape = self..drawSquare(dc.setX(i.zetcode.setX(i...pieceShape == Tetrominoes.board = [] .pieceShape = self. The self.setY(i. Before we start the game cycle. we initialize some important variables.NoShape: self. for i in range(Board.) The game goes at constant speed. .. 8 de 12 27/04/2008 1:10 . The space key will drop the tetris piece immediately to the bottom. -self.BoardHeight . It represents the position of various shapes and remains of the shapes on the board. The score is the number of lines. that we have removed. self.MainLoop() I have simplified the game a bit.shapeAt(j.board variable is a list of numbers from 0 .The Tetris game in wxPython http://www. 0 + x * self. If we try. press the left arrow key. we position and return true. that have been in the self. self. self.shapeAt(x. we try to move the piece to the left. newPiece. boardTop + i * self.squareWidth().shape() != Tetrominoes.The Tetris game in wxPython http://www. We say def tryMove(self.curX = newX self.y .newPiece.squareHeight(). We access it using the shapeAt() method.curPiece.curX .shape()) The next step is drawing of the actual piece.1.x(i) y = newY .curPiece.curY .zetcode.curPiece.com/wxpython/thetetrisgame/ 0 + j * self. All the squares are rememberd if self. shape) The painting of the game is divided into two steps. self.BoardHeight . dropped to the bottom of the board. we draw all the shapes.NoShape: for i in range(4): x = self.squareHeight(). that is falling down. or remains of the shapes.board list variable. boardTop + (Board.curY = newY self. Otherwise we place the current falling piece to a new 9 de 12 27/04/2008 1:10 .curPiece = newPiece self.WXK_LEFT: self. return false. If the shape is at the edge of the board or is adjacent to some other piece.tryMove(self.self.curY) In the OnKeyDown() method we check for pressed keys.NoShape: return False self. elif keycode == wx.BoardWidth or y < 0 or y >= Board.drawSquare(dc.Refresh() return True In the tryMove() method we try to move our shapes.curX + self.curPiece. In the first step. because the piece might not be able to move.x(i) y = self.BoardHeight: return False if self.1) * self.y(i) self. newX.y(i) if x < 0 or x >= Board.curPiece. y) != Tetrominoes. newY): for i in range(4): x = newX + newPiece.squareWidth(). Otherwise. we call the removeFullLines() method. k + 1)) . i) == Tetrominoes.. moving all lines above the current full line to be removed one line down. self.isWaitingAfterLine = False self. Notice.BoardWidth): if not self.newPiece() else: self.NoShape: n = n + 1 if n == 10: rowsToRemove.BoardHeight): for l in range(Board. First we find out all full lines. it would not work correctly. This means.zetcode. k.. And we remove them. that the pieces may be floating above empty gaps. event): if event. We do it by If the piece hits the bottom.append(i) rowsToRemove.shapeAt(j.com/wxpython/thetetrisgame/ def OnTimer(self.GetId() == Board. after the previous one was dropped to the bottom. def removeFullLines(self): numFullLines = 0 rowsToRemove = [] for i in range(Board.BoardWidth): self. or we move a falling piece one line down.oneLineDown() else: event.The Tetris game in wxPython http://www. In our case we use a naive gravity.isWaitingAfterLine: self. 10 de 12 27/04/2008 1:10 .reverse() for m in rowsToRemove: for k in range(m.Skip() In the OnTimer() method we either create a new piece. Board. that we reverse the order of the lines to be removed.BoardHeight): n = 0 for j in range(Board.setShapeAt(l.ID_TIMER: if self.shapeAt(l. coords = [[0. Figure: Coordinates When we draw the current falling piece. The list will save (0.curY = Board.setShape(Tetrominoes. the game is over.com/wxpython/thetetrisgame/ def newPiece(self): self. The Shape class saves information about the tetris piece.zetcode.curPiece. these tuples (0. 0). all the four squares. the coordinates of the tetris piece.nextPiece. For example.BoardWidth / 2 + 1 self. If the piece cannot go into it's initial position. self.curPiece. -1). self.timer. self.curX = Board. (1.curPiece.curY position. self.Stop() self.isStarted = False statusbar.tryMove(self.curX.nextPiece statusbar = self.BoardHeight .The Tetris game in wxPython http://www.statusbar self. The following diagram illustrates the shape. (1.setRandomShape() self. 1) represent a rotated S-shape. we draw it at self.NoShape) self.curY): self. Then we look at the coordinates table and draw 11 de 12 27/04/2008 1:10 .minY() if not self. 0).1 + self.0] for i in range(4)] Upon creation we create an empty coordinates list.SetStatusText('Game over') The newPiece() method creates randomly a new tetris piece.curX.curPiece = self.GetParent(). 2007 © 2007 Jan Bodnar 12 de 12 27/04/2008 1:10 .The Tetris game in wxPython http://www. Community and Competition.zetcode. Browser. Debugger.com/wxpython/thetetrisgame/ Figure: Tetris Play Free Online Games wxPython Coding Tools Enjoy over 50 Online Games for free Games. Editor. and more Take Home ‡ Contents ‡ Top of Page ZetCode last modified November 25.
Copyright © 2024 DOKUMEN.SITE Inc.