为了实现一个管理本地电子书的程序,搞了一段时间 GUI,使用 wxPython。
实在难以适应和习惯,也搞不出什么太好看的效果。
最不能忍受的是,多线程处理能力太弱。遂决定放弃 GUI。
放弃之前,整理一点笔记。
1. GUI 的基本原理与框架
GUI 的核心都是基于事件编程,开启一个loop,不停的监听事件。
监听到事件以后,交给对应的 handler 来处理。
wxPython 中,需要有一个 wx.App 和 至少一个 Frame。
wx.App 管理程序的生命周期,比如,开启一个 loop。
wx.Frame 内添加各种控件 widgets 控制样式和具体的行为。
GUI 中的窗口,除了wx.Frame,还是wx.Dialog, wx.Dialog 多为 Modal 模式。
Modal 模式,即阻塞了别的窗口部件接收用户事件,直到该模式对话框被关闭。
二者在使用和运行机制上,略有差别,参见 wxPython Modal Dialog 模式对话框
2. GUI 的多线程
GUI的操作必须发生在主线程或应用程序的主循环所处的地方中。
在一个单独的线程中执行GUI操作,容易导致无法预知的程序崩溃,而且难以调试。
基于技术方面的原因,
如许多Unix的GUI库不是线程安全性的,以及在微软Windows下UI对象的创建问题,
wxPython没有设计它自己的发生在多线程中的事件。
我们自己最好也不要尝试。
理想的情况是,对于 UI 的更新,后台线程只负责发送消息给 UI 线程,而不关心 GUI 的更新。
幸运的是,wxPython没有强制限定你能够有的后台线程的数量。
但是,实践中,子线程内的 IO 缓存等原因,搞得我不得不去考虑 UI 更新问题。
然后,考虑完了也没有搞懂这个场景:
普通方式或者 wx.CallAfter 调用耗时长的任务,然后在任务中用 AppendText 给 wx.TextCtrl 控件追加文本,任务结束前都不会更新 UI。
貌似在任务中应该触发一个事件,然后在事件的 handler 中追加文本,而不是在 任务中追求文本。
3. sizer 控制样式
sizer 内可以直接 Add(seizer), 像 Add 其他控件一样。
最终需要把主 sizer SetLayout 即可。