WxPython FAQ First Steps

Материал из Wiki.crossplatform.ru

Версия от 09:11, 19 февраля 2009; ViGOur (Обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

Simple example

We start with a very simple example. Our first script will only show a small window. It won't do much. We will analyze the script line by line. Here is the code:

#!/usr/bin/python
# simple.py
 
import wx
 
app = wx.App()
 
frame = wx.Frame(None, -1, 'simple.py')
frame.Show()
 
app.MainLoop()
#!/usr/bin/python
# simple.py

The first line is a she-bang followed by the path to a python interpreter. The second line is a comment. It provides a name for the script.

import wx

This line imports the basic wxPython modules. Namely the core, controls, gdi, misc and windows. Technically wx is a namespace. All functions and objects from the basic modules will start with a wx. prefix. The next line of code will create an application object.

app = wx.App()

Each wxPython program must have one application object.

frame = wx.Frame(None, -1, 'simple.py')
frame.Show()

Here we create a wx.Frame object. A wx.Frame widget is an important container widget. We will analyze this widget in detail later. The wx.Frame widget is a parent widget for other widgets. It has no parent itself. If we specify None for a parent parameter we indicate that our widget has no parents. It is a top widget in the hierarchy of widgets. After we create the wx.Frame widget, we must call the Show() method to actually display it on the screen.

app.MainLoop()

The last line enters the mainloop. The mainloop is an endless cycle. It catches and dispatches all events that exist during the life of our application.

This was a very simplistic example. Despite this simplicity we can do quite a lot with this window. We can resize the window, mazimize it, minimize it. This functionality requires a lot of coding. All this is hidden and provided by default by the wxPython toolkit. There is no reason for reinventing the wheel.

center


wx.Frame

wx.Frame widget is one of the most important widgets in wxPython. It is a container widget. It means that it can contain other widgets. Actually it can contain any window that is not a frame or dialog. wx.Frame consists of a title bar, borders and a central container area. The title bar and borders are optional. They can be removed by various flags.

wx.Frame has the following constructor. As we can see, it has seven parameters. The first parameter does not have a default value. The other six parameters do have. Those four parameters are optional. The first three are mandatory.


  wx.Frame(wx.Window parent, int id=-1, string title='', wx.Point pos = wx.DefaultPosition, 
  wx.Size size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, string name = "frame")

wx.DEFAULT_FRAME_STYLE is a set of default flags. wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN. By combining various styles we can change the style of the wx.Frame widget. A short example follows.

#!/usr/bin/python
# nominimizebox.py
 
import wx
 
app = wx.App()
window = wx.Frame(None, style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER 
	| wx.SYSTEM_MENU | wx.CAPTION |	 wx.CLOSE_BOX)
window.Show(True)
 
app.MainLoop()

Our intention was to display a window without a mimimize box. So we did not specify this flag in the style parameter.

center

Size and Position

We can specify the size of our application in two ways. We have a size parameter in the constructor of our widget. Or we can call the SetSize() method.

#!/usr/bin/python
# size.py
 
import wx
 
class Size(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 200))
 
        self.Show(True)
 
 
app = wx.App()
Size(None, -1, 'Size')
app.MainLoop()
 wx.Frame.__init__(self, parent, id, title, size=(250, 200))

In the constructor we set the width of the wx.Frame widget to 250px. The height of the widget to 200px.

Similarly, we can position our application on the screen. By default the window is placed in the upper left corner of the screen. But it can differ on various OS platforms or even window managers. Some window managers place application windows themselves. Some of them do some optimalization, so that windows do not overlap. A programmer can position the window programmatically. We already saw a pos parameter in the constructor of our wx.Frame widget. By providing other than the default values, we can control the position ourselves.

Method Description
Move(wx.Point point) move a window to the given position
MoveXY(int x, int y) move a window to the given position
SetPosition(wx.Point point) set the position of a window
SetDimensions(wx.Point point, wx.Size size) set the position and the size of a window

There are several methods to do this. Toss a coin.

#!/usr/bin/python
# move.py
 
import wx
 
class Move(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title)
 
        self.Move((800, 250))
        self.Show(True)
 
 
app = wx.App()
Move(None, -1, 'Move')
app.MainLoop()

There is one particular situation. We might want to display our window maximized. In this case, the window is positioned at (0, 0) and takes the whole screen. wxPython internally calculates the screen coordinates. To maximize our wx.Frame, we call the Maximize() method. If we want to center our application on the screen, wxPython has a handy method. The Centre() method simply centers the window on the screen. No need to calculate the width and the height of the screen. Simply call the method.

#!/usr/bin/python
# centre.py
 
import wx
 
class Centre(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title)
 
        self.Centre()
        self.Show(True)
 
app = wx.App()
Centre(None, -1, 'Centre')
app.MainLoop()

Widgets communicate

It is important to know, how widgets can communicate in application. Follow the next example.

#!/usr/bin/python
# communicate.py
 
import wx
 
 
class LeftPanel(wx.Panel):
    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
 
        self.text = parent.GetParent().rightPanel.text
 
        button1 = wx.Button(self, -1, '+', (10, 10))
        button2 = wx.Button(self, -1, '-', (10, 60))
 
        self.Bind(wx.EVT_BUTTON, self.OnPlus, id=button1.GetId())
        self.Bind(wx.EVT_BUTTON, self.OnMinus, id=button2.GetId())
 
    def OnPlus(self, event):
        value = int(self.text.GetLabel())
        value = value + 1
        self.text.SetLabel(str(value))
 
    def OnMinus(self, event):
        value = int(self.text.GetLabel())
        value = value - 1
        self.text.SetLabel(str(value))
 
 
class RightPanel(wx.Panel):
    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
        self.text = wx.StaticText(self, -1, '0', (40, 60))
 
 
class Communicate(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(280, 200))
 
        panel = wx.Panel(self, -1)
        self.rightPanel = RightPanel(panel, -1)
 
        leftPanel = LeftPanel(panel, -1)
 
        hbox = wx.BoxSizer()
        hbox.Add(leftPanel, 1, wx.EXPAND | wx.ALL, 5)
        hbox.Add(self.rightPanel, 1, wx.EXPAND | wx.ALL, 5)
 
        panel.SetSizer(hbox) 
        self.Centre()
        self.Show(True)
 
app = wx.App()
Communicate(None, -1, 'widgets communicate')
app.MainLoop()

In our example we have two panels. A left and right panel. The left panel has two buttons. The right panel has one static text. The buttons change the number displayed in the static text. The question is, how do we grab the reference to the static text?

If all the widgets are within one class, it is trivial. But what if those widgets are created in different classes? In such situations, we must get the reference via the hierarchy.

 panel = wx.Panel(self, -1)
 self.rightPanel = RightPanel(panel, -1)
 
 leftPanel = LeftPanel(panel, -1)

Notice that the right panel must be defined before the left panel. It is because during the construction of the left panel, we are looking for the static text widget, which is defined in the right panel. Logically, we cannot get reference to non existing widget.

 self.text = parent.GetParent().rightPanel.text

The answer is here. Each widget has a parent argument. In our example, parent is a panel on which we display both left and right panels. By calling parent.GetParent() we get reference to the frame widget. The frame widget has reference to the rightPanel. Finally, right panel has reference to the static text widget.

center