12.1 丰富的平台
在编写python GUI程序前,需要决定使用哪个GUI平台。wxpython----跨平台pythonGUI工具包
确保所选择的二进制版本要对应python的版本,例如,针对python2.3进行编译的wxpython并不能用于python2.4.
12.3.1 开始
开始需要wx模块:
import wx
编写wxPython程序的方法很多,但不可避免的事情是创建应用程序对象。基本的应用程序类叫做ex.App,它负责幕后所有的初始化。最简单的wxPython程序应该像下面这样:
import wx
app = wx.App
app.MainLoop()
如果wx.App无法工作,可能需要将它替换为wx.PySimpleApp
12.3.2 窗口和组件
窗口也称为框架,它只是wx.Frame类的实例。wx框架中的部件都是由它们的父部件作为构造函数的第一个参数的第一个参数创建的。如果正在创建一个单独的窗口,就不需要考虑父部件,使用None即可,如代码清单12-1所示。而且在调用app.MainLoop前需要调用窗口的Show方法-----否则它会一直隐藏。
创建并且显示一个框架
import wx
app = wx.App()
win = wx.Frame(None)
win.Show()
app.MainLoop()
在框架上增加按钮也很简单----只要使用win作为父参数实例化wx.Button即可
在框架上增加按钮
import wx
app = wx.App()
win = wx.Frame(None)
btn = wx.Button(win)
win.show()
app.MainLoop()
12.3.3 标签、标题和位置
可以在创建部件的时候使用构造函数的label参数设定它们的标签。同样,也可以用title参数设定框架的标题。
使用关键字参数增加标签和标题
import wx
app = wx.App()
win = wx.Frame(None,title="Simple Editor")
loadButton = wx.Button(win,label='Open')
saveButton = wx.Button(win.label='Save')
win.Show()
app.MainLoop()
注意一下按钮的布局就能将隐藏的按钮显示。一个很基础的方法是使用pos和size参数在构造函数内设置位置和尺寸。
设置按钮位置
import wx
app = wx.App()
win = wx.Frame(None,title="Simple Editor",size=(410,335))
win.Show()
loadButton = wx.Button(win,label='Open',pos=(315,5),size=(80,25))
saveButton = wx.Button(win,label='Save',pos=(315,5),size=(80,25))
filename = wx.TextCtrl(win,pos=(5,5),size=(210,25))
contents = wx.TextCtrl(win,pos=(5,35),size=(390,260),style=wx.TE_MULTILINE | wx.HSCROLL)
app.MainLoop()
位置和尺寸都包括一对数值:位置包括x和y坐标,而尺寸包括宽和高。
创建了两个文本控件,每个都使用了自定义风格。默认的文本控件式文本框,就是一行可编辑的文本,没有滚动条,为了创建文本区只要使用style参数调整风格即可。style参数的值实际上是个整数。但不用直接指定,可以使用按位或运算符OR联合wx模块中具有特殊名字的风格来指定。本例中,我联合了wx.TE_MULTINE来获取多行文本区以及wx.HSCROLL来获取水平滚动条。
12.3.4 更智能的布局
让组件随窗口中的组件也会调整大小和位置。
使用尺寸器
import wx
app = wx.App()
win = wx.Frame(None,title="Simple Editor",size=(410,335))
bkg = wx.Panel(win)
loadButton = wx.Button(bkg,label='Open')
saveButton = wx.Button(bkg,label='Save')
filename = wx.TextCtrl(bkg)
contents = wx.TextCtrl(bkg,style=wx.TE_MULTILINE | wx.HSCROLL)
hbox = wx.BoxSizer()
hbox.Add(filename,proportion=1,flag=wx.EXPAND)
vbox.Add(loadButton,proportion=0,flag=wx.LEFT,border=5)
hbox.Add(saveButton,proportion=0,flag=wx.LEFT,border=5)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox,proportion=0,flag=wx.EXPAND | wx.ALL,border=5)
vbox.Add(contenxs,proportion=1,flag=wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT,border=5)
bkg.SetSizer(vbox)
win.Show()
app.MainLoop()
这段代码的运行结果和前例相同,但是使用了相对坐标而不是绝对坐标。
wx.BoxSizer的构造函数带有一个决定它是水平还是垂直的参数(wx.HORIZONTAL或者wx.VERTICAL),默认为水平。Add方法有几个参数,proportion参数根据在窗口改变大小时所分配的空间设置比例。例如,水平的BoxSizer中,filename组件的改变大小时获取了全部的额外空间。如果这3个部件都把proportion设为1,那么都会获得相等的空间。可以将proportion设定为任何数。
flag参数类似构造函数中的style参数,可以使用按位或运算符连接构造符号常量对其进行构造。wx.EXPAND标记确保组件会扩展到所分配的空间中。而wx.LEFT,wx.RIGHT,wx.TOP,wx.BOTTOM和wx.ALL标记决定边框参数应用于哪个边,边框参数用于设置边缘宽度。
12.3.5 事件处理
在GUI术语中,用户执行的动作叫做事件。你需要让程序注意这些事件并且作为反应。可以将函数绑定到所涉及的事件可能发生的组件上达到这个效果。当事件发生时,函数会被调用。利用部件的Bind方法可以将事件处理函数链接到给定的事件上。
假设写了一个负责打开文件的函数,并将其命名为load。然后就可以像下面这样将该函数作为loadButton的事件处理函数:
loadButton.Bind(wx.EVT_BUTTON,load)
我把函数链接到了按钮---点击按钮的时候,函数被调用。名为wx.EVT_BUTTON的符号常量表示一个按钮事件。wx框架对于各种事件都有这样的事件常量----从鼠标动作到键盘按键。
12.3.6 完成了的程序
现在需要两个事件处理函数:load和save。当事件处理函数被调用时,它会收到一个事件对象作为它唯一的参数,其中包括发生了什么事情的信息,但是在这里可以忽略这方面的事情,因为程序只关心点击时发生的事情。
def load(event):
file = open(filename.GetValue())
contents.SetValue(file.read())
file.close()
def save(event):
file = open(filename.GetValue(),'w')
file.write(contents.GetValue())
file.close()
最终的GUI程序
import wx
def load(event):
file = open(filename.GetValue())
contents.SetValue(file.read())
file.close()
def save(event):
file = open(filename.GetValue(),'w')
file.write(contents.GetValue())
file.close()
app = wx.App()
win = wx.Frame(None,title="Simple Editor",size=(410,335))
bkg = wx.Panel(win)
loadButton = wx.Button(bkg,label='Open')
loadButton.Bind(wx.EVT_BUTTON,load)
saveButton = wx.Button(bkg,label='Save')
saveButton.Bind(wx.EVT_BUTTON,save)
filename = wx.TextCtrl(bkg)
contents = wx.TextCtrl(bkg,style=wx.TE_MULTILINE | wx.HSCROLL)
hbox = wx.BoxSizer()
hbox.Add(filename,proportion=1,flag=wx.EXPAND)
vbox.Add(loadButton,proportion=0,flag=wx.LEFT,border=5)
hbox.Add(saveButton,proportion=0,flag=wx.LEFT,border=5)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox,proportion=0,flag=wx.EXPAND | wx.ALL,border=5)
vbox.Add(contenxs,proportion=1,flag=wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT,border=5)
bkg.SetSizer(vbox)
win.Show()
app.MainLoop()
可以按照下面的步骤使用这个编辑器。
1.运行程序。应该看到一个和刚才差不多的窗口
2.在文本区里面打些字
3.在文本框内键入文件名。确保文件不存在,否则它会被覆盖。
4.点击save按钮
5.关闭编辑器窗口
6.重启程序
7.在文本框内键入同样的文件名
8.点击open按钮。文件的文本内容应该会在大文本区内重现。
9.随便编辑一下文件,再次保存。
12.4 但是我宁愿用。。。
python的GUI工具包实在太多,所以我没法将所有工具包都展示给你看。不过我可以给出一些流行的GUI包中的例子。
import wx
def hello(event):
print "Hello,world!"
app = wx.App()
win = wx.Frame(None,title="Hello,wxPython!",size=(200,100))
button = wx.Button(win,label="Hello")
button = Bind(wx.EVT_BUTTON,hello)
win.Show()
app.MainLoop()
12.4.1 使用Tkinter
Tkinter是个老牌的Python GUI程序。它由Tk GUI工具包包装而来。
from Tkinter import *
def hello(): print 'Hello,world'
win = Tk()
win.title('Hello,Tkinter!')
win.geometry('200*100')
btn = Button(win,text='Hello ',command=hello)
btn.pack(expand=YES,fill=BOTH)
mainloop()
12.4.2 使用jython和Swing
如果正在使用jython,类似wxPython和Tkinter这样的包就不能用了。唯一可用的GUI工具包是java标准库包AWT和Swing。
下面是使用jython和Swing实现的GUI示例
from javax.Swing import *
import sys
def hello(event): print 'Hello,world!'
btn = JButton('Hello')
btn.actionPerformed = hello
win = JFrame('Hello,Swing!')
win.contenPane.add(btn)
def closeHandler(event): sys.exit()
win.windowClosing = closeHandler
btn.size = win.size = 200,100
win.show()
这里增加了一个额外的事件处理函数,因为关闭按钮在java Swing中没有任何有用的默认行为。另外,无须显式地进入主事件循环,因为它是和程序并运行的。