第一次写完整的Python GUI程序

 夜里用外挂容易被查,因此想让菜熟的时间集中到白天,每次都要口算,麻烦,正好刚刚学了wxPython,一时手痒,来自己写个吧。虽说纯属自娱自乐,但也学到不少东西。现记于下。

 

1. 关于Python的GUI设计

一直以来都没有一个足够好的Killer IDE,这也怪不得,没有一个足够强大的后台,要想做成重量级的IDE谈何容易(要是Google拉一把就好了,可惜Google出了自己的语言Go)。

 

试过无数设计器(wxGlade、wxFormBuilder、FarPy...),最终还是觉得Boa Constructor不错,虽然它的界面不习惯(P.S.一定不要最大化运行Boa就行了,当然手动双击是没这问题的,但是用一些快捷管理工具就难说了 还有就是F9直接运行整个项目,挺方便 );虽然它中文支持得不好;虽然它还是07年更新过。。。

 

但这已经是这些当中最好用的了。

 

针对以上的不足,我只好增加“人手”帮忙了:

用Boa构建纯GUI,几乎没有任何业务逻辑。另外在Boa生成的文件中_init_ctrls 里面的代码一定别去碰它 ,否则会造成Frame Designer无法加载,而这就是Boa最有价值的所在了。但Boa没有什么代码提示(可以在Explorer->Preferences->key bindings下面设置),编辑功能也比下面两者弱不少,就只用它来做GUI了。(P.S.一定要用源码而不是二进制,可以较好地支持Unicode

 

业务逻辑的代码用PyDev,这是个非常优秀的IDE,基于Eclipse,此次我也学习到了它更多的用法。(如Edit->Set Encoding、在Src上右键Refresh等等)

 

修改Boa生成的Python代码我用PyScripter,原因有三:没找到Eclipse怎么加入它(太笨,后来摸出来是Src上右键Refresh)、修改编码格式(现在知道可以用Eclipse的Set Encoding)、对wxPython的函数提示支持比Eclipse好(这一点我目前还没找到好的解决方法,P.S.手动加入模块路径即可 )。再说PyScripter还有个比IDLE好用得多的命令行工具。另外用它对一些功能做做测试也不错(P.S. Pydev也可以,锁定一个Console为Python Console就行了 )。

 

三者配合,再加上wxPython的Demonstration、Python的官方文档,以及万能的Google,开发起来还算不错了。

 

2. 关于Python语言学到的

①将GUI与业务逻辑几乎(大概90%)完全分开,从中体会到了这种设计对于测试的方便性、业务与GUI分离带来的代码清晰。

②类的静态方法:

@staticmethod def GetCurrentTime(): pass

③用datetime对时间进行方便的加减:

import datetime #过ahour小时aminute分钟之后是什么时间 dt = datetime.datetime(year=2009, month=11, day=11, hour=ahour, minute=aminute) delta = datetime.timedelta(hours = bhour) dt += delta print dt.strftime('%H:%M')

另外CSDN的一个贴子中说有parse,什么时候试试。

 

④在wxPython中使用多个定时器

def InitData(self): #所有的定时器都绑定到同一个函数 self.Bind(wx.EVT_TIMER, self.OnTimer) #最后一个参数ID就是用来区分不同的定时器的 self.tm1 = wx.Timer(self, 1) self.tm1.Start(1000) self.tm2 = wx.Timer(self, 2) self.tm2.Start(1000) def OnTimer(self, evt): id = evt.GetId() if id == 1: pass elif id == 2: pass

P.S.后来在《wxPython in Action 》的最后一章看到另一个方法:

timer1 = wx.Timer(self)  timer2 = wx.Timer(self)  self.Bind(wx.EVT_TIMER, self.OnTimer1Event, timer1)  self.Bind(wx.EVT_TIMER, self.OnTimer2Event, timer2) 

⑤使用多线程程序

后来我又试验用多线程来模拟多个定时器的办法,尽管没这必要,但学到了东西。

def InitData(self): self.timeAt.SetValue('10:30') #use thread to set timer to refresh current time threadGetTime = threading.Thread(target=self.TimerGetTime) #设置daemon属性很重要,因此如果不设置dameon为Ture的话, #当主进程结束时,整个程序仍然要等每个线程都结束了才能结 #束,而这里线程中的函数都是无限循环,所以只有等到对窗口部件 #的操作失败才会退出,因此程序结束后总要等一会儿 #而daemon为True以后,主进程结束时会立即强制结束所有线程 threadGetTime.daemon = True threadGetTime.start() #set timer to update crop time threadUpdate = threading.Thread(target=self.TimerUpdateCrop) threadUpdate.daemon = True threadUpdate.start() def TimerUpdateCrop(self): while True: self.FillCrop() time.sleep(60) def TimerGetTime(self): while True: self.MatureTime() time.sleep(1)

另外,IBM上的一篇文章建议在Python中用进程而非线程:

全局解释器锁 (Global Interpretor Lock) 说明 Python 解释器并不是线程安全的。当前线程必须持有全局锁,以便对 Python 对象进行安全地访问。因为只有一个线程可以获得 Python 对象/C API,所以解释器每经过 100 个字节码的指令,就有规律地释放和重新获得锁。解释器对线程切换进行检查的频率可以通过 sys.setcheckinterval() 函数来进行控制。

此外,还将根据潜在的阻塞 I/O 操作,释放和重新获得锁。有关更详细的信息,请参见参考资料 部分中的 Gil and Threading StateThreading the Global Interpreter Lock

需要说明的是,因为 GIL,CPU 受限的应用程序将无法从线程的使用中受益。使用 Python 时,建议使用进程,或者混合创建进程和线程。

在Python2.6中提供了multiprocessing这样一个很棒的模块,一举将线程这个软肋去掉,多进程成为强项。

The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads. Due to this, the multiprocessing module allows the programmer to fully leverage multiple processors on a given machine. It runs on both Unix and Windows.

(PS: 实际使用中发现multiprocessing在Windows平台上有不少的限制,其中一个就是要求picklable )

 

⑥在Python中使用了单元测试:

import FarmTimer import unittest class FarmTimerTestCase(unittest.TestCase): def SetUp(self): self.farmTimer = FarmTimer() def TearDown(self): self.farmTimer = None def testGetTimeDelta(self): self.assertEqual(datetime.timedelta(minutes=2), FarmTimer.Farm.GetTimerDelta("00:02")) if __name__ == '__main__': unittest.main()

 

⑦使用了sqlite,只是后来发现这么点数据实在不值得用数据库,于是直接用tuple of tuple:

crops = (
    #name, rank, count, (times,)
    #can be added col before time
    (u'牧草', 0, 1, (8,)),
    (u'白萝卜', 0, 1, (10,)),

   ...)

 

小结:学程序是要靠多写的,写一个小程序就让我写到了这么多,而且还留下很多值得继续深入的话题,比如:Py2exe打包后在XP上无法正常运行、mutiprocess模块的使用等等。我一定还会回来的!

你可能感兴趣的:(eclipse,timer,python,concurrency,wxPython,encoding)