使用WxPython进行Win32下Python编程(五)
作者:Mark Hammond 和 Andy Robinson 翻译:limodou
如果你检查wxPython窗口布局的工具条,会看到许多可用的选择,但我们选用了强制力机制作用于交易编辑对话框:
# 创建控件
wxStaticText(self, -1, "Date:", wxDLG_PNT(self, 5,5))
self.date = wxTextCtrl(self, ID_DATE, "",
wxDLG_PNT(self, 35,5), wxDLG_SZE(self, 50,-1))
wxStaticText(self, -1, "Comment:", wxDLG_PNT(self, 5,21))
self.comment = wxTextCtrl(self, ID_COMMENT, "",
wxDLG_PNT(self, 35, 21), wxDLG_SZE(self, 195,-1)
这些代码展示了如何在对话框上面创建标签和文本框。注意wxDLG_PNT和wxDLG_SZE的用法,它们分别将对话框单位转化为wxPoint和wxSize。(上面用到的-1表示高度使用缺省尺寸。)不用像素而使用对话框单位来定义对话框意味着当对话框中使用的字体改变时不会受到太大的影响。wxPoint和wxSize总是用像素来定义的,这样当从一台机器转到另一台使用不同字体的机器上时,这些转换函数允许所用的实际像素值自动进行调整。这就使得在有着完全不同的窗口管理机制的平台之间转移程序变得容易。图8演示了同样的程序在RedHat linux 6.0下的情况,你可以看出对于大部分来说,尽管在表单上使用了完全不同的字体,这些控件的占位仍然适当。看上去wxTextCtrl在这个平台上高了几个对话框单位,所以也许应该在行之间多留一些空间。把它做为一个练习留给你。
图8.在Redhat Linux 6.0上运行的Doubletalk编辑器
下一个将要定义的控件是wxListCtrl,它用来显示帐号和金额行:
self.lc = wxListCtrl(self, ID_LIST,
wxDLG_PNT(self, 5,34), wxDLG_SZE(self, 225,60),
wxLC_REPORT)
self.lc.InsertColumn(0, "Account")
self.lc.InsertColumn(1, "Amount")
self.lc.SetColumnWidth(0, wxDLG_SZE(self, 180,-1).width)
self.lc.SetColumnWidth(1, wxDLG_SZE(self, 40,-1).width)
注意这个控件的宽度是225个对话框单位,这一点很重要。因为这个控件横跨整个对话框,你知道正在处理的空间。当需要决定放置的地方或如何设置其它控件的大小时,你可以使用这个值。
不要使用这个列表框列的自动大小调整功能,让我们使用确定的大小。但是你仍然可以用对话框单位来处理它,通过使用从wxSize(从wxDLG_SZE中返回)对象中提取出来的宽度属性。我们应该提醒以下几点:
balance字段被禁止了,因为你仅想用它来显示一个值。
使用一个wxStaticLine控件来绘制一长横穿对话框的线。
一个wxComboBox被用来从一个列表中选择存在的帐户名。
使用标准的ID定义wxID_OK和wxID_CANCEL分别用于OK和Cancel按钮,并且将OK按钮设为缺省按钮。
调用基类的Fit()方法来初始化对话框窗口的大小。这个函数根据在每个子类中指定的尺寸信息来计算整个所需的大小。
下面是创建这些控件的剩余的代码:
wxStaticText(self, -1, "Balance:", wxDLG_PNT(self, 165,100))
self.balance = wxTextCtrl(self, ID_BAL, "",
wxDLG_PNT(self, 190,100),
wxDLG_SZE(self, 40, -1))
self.balance.Enable(false)
wxStaticLine(self, -1, wxDLG_PNT(self, 5,115),
wxDLG_SZE(self, 225,-1))
wxStaticText(self, -1, "Account:", wxDLG_PNT(self, 5,122))
self.account = wxComboBox(self, ID_ACCT, "",
wxDLG_PNT(self, 30,122), wxDLG_SZE(self, 130,-1),
accountList, wxCB_DROPDOWN | wxCB_SORT)
wxStaticText(self, -1, "Amount:", wxDLG_PNT(self, 165,122))
self.amount = wxTextCtrl(self, ID_AMT, "",
wxDLG_PNT(self, 190,122),
wxDLG_SZE(self, 40, -1))
btnSz = wxDLG_SZE(self, 40,12)
wxButton(self, ID_ADD, "&Add Line", wxDLG_PNT(self, 52,140), btnSz)
wxButton(self, ID_UPDT, "&Update Line", wxDLG_PNT(self, 97,140),
btnSz)
wxButton(self, ID_DEL, "&Delete Line", wxDLG_PNT(self, 142,140),
btnSz)
self.ok = wxButton(self, wxID_OK, "OK", wxDLG_PNT(self, 145,5),
btnSz)
self.ok.SetDefault()
wxButton(self, wxID_CANCEL, "Cancel", wxDLG_PNT(self, 190,5), btnSz)
# 重新设置窗口大小,来适应控件
self.Fit()
最后一件要做的事情是创建一些事件处理器,然后给对话框控件填入数据。对控件的事件处理几乎同前面讨论过的菜单的处理一样,所以这里应该没有什么问题:
# 设置一些事件处理器
EVT_BUTTON(self, ID_ADD, self.OnAddBtn)
EVT_BUTTON(self, ID_UPDT, self.OnUpdtBtn)
EVT_BUTTON(self, ID_DEL, self.OnDelBtn)
EVT_LIST_ITEM_SELECTED(self, ID_LIST, self.OnListSelect)
EVT_LIST_ITEM_DESELECTED(self, ID_LIST, self.OnListDeselect)
EVT_TEXT(self, ID_DATE, self.Validate)
# 用当前值初始化控件
self.date.SetValue(self.trans.getDateString())
self.comment.SetValue(self.trans.comment)
for x in range(len(self.trans.lines)):
account, amount, dict = self.trans.lines[x]
self.lc.InsertStringItem(x, account)
self.lc.SetStringItem(x, 1, str(amount))
self.Validate()
这段代码所做的最后一件事情是调用Validate()方法,正如你可能猜到的,它负责校验对话框的数据;在本例中,校验日期的正确性,并且校验所有交易行的总和应该为0。当字段改变时对日期进行校验(通过代码列出的EVT_TEXT()调用),并且在任何时候当增加或修改一行时检查平衡。只要有不正确的,禁止OK按钮。下面是Validate代码:
def Validate(self, *ignore):
bal = self.trans.balance()
self.balance.SetValue(str(bal))
date = self.date.GetValue()
try:
dateOK = (date == dates.testasc(date))
except:
dateOK = 0
if bal == 0 and dateOK:
self.ok.Enable(true)
else:
self.ok.Enable(false)
注意balance字段被更改了。我们要做的下一件事情是增加一行的功能。为了做到这一点,需要使用帐号(account)和数量(amount)字段的值,把它们加到交易中,然后还要把它们加到列表控件中:
def OnAddBtn(self, event):
account = self.account.GetValue()
amount = string.atof(self.amount.GetValue())
self.trans.addLine(account, amount)
# update the list control
idx = len(self.trans.lines)
self.lc.InsertStringItem(idx-1, account)
self.lc.SetStringItem(idx-1, 1, str(amount))
self.Validate()
self.account.SetValue("")
self.amount.SetValue("")
再次调用Validate来检查是否交易的各行是平衡的。对于修改(Update)和删除(Delete)按钮的事件处理器很相似,这里就不再列出了。
这些基本上就是全部内容了!wxPython使用tab键在字段之间进行切换,按了回车键自动完成,按了ESC键取消,还有一些别的。
wxPython 结论
这一小段刚刚能够触及wxPython功能的表面。除了在这里演示的之外,还有更多的窗口和控件类型,并且许多高级的特性使得它们具有很高的灵活性,并且可以实现许多跨平台的动态GUI应用。同Python的灵活性相融合,你最终得到的是一个快速创建世界级应用的强大工具。
想要了解关于wxPython的更多的信息,包括大量的文档和例程,参观wxPython主页。
想要了解关于底层的wxWindows框架的更多的信息,请参观它的主页。