为了实现一个管理本地电子书的程序,搞了一段时间 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没有设计它自己的发生在多线程中的事件。
我们自己最好也不要尝试。
后台执行长时间运行的程序,并在界面上显示进度。
实现的原理如下图:
在 main_thread 上创建子线程,用于执行长时间运行的程序。
子线程只负责给 main_thread(UI 线程)发消息,而不关心 GUI 的更新。
主线程响应子线程触发的事件,不如,更新 UI。
最简单的实现方式是,
子线程调用 wx.CallAfter(func, (args)) 注册新事件,并将 func 注册到新事件的处理句柄中。
新消息执行时,func 在主线程中执行并更新UI。
也可以自定义事件,自定义处理句柄。
3. sizer 控制样式
sizer 内可以直接 Add(seizer), 像 Add 其他控件一样。
最终需要把主 sizer SetLayout 即可。