为了实现一个管理本地电子书的程序,搞了一段时间 GUI,使用 wxPython。
实在难以适应和习惯,也搞不出什么太好看的效果。
最不能忍受的是,多线程处理能力太弱。遂决定放弃 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 模式对话框
GUI的操作必须发生在主线程或应用程序的主循环所处的地方中。
在一个单独的线程中执行GUI操作,容易导致无法预知的程序崩溃,而且难以调试。
基于技术方面的原因,
如许多Unix的GUI库不是线程安全性的,以及在微软Windows下UI对象的创建问题,
wxPython没有设计它自己的发生在多线程中的事件。
我们自己最好也不要尝试。
后台执行长时间运行的程序,并在界面上显示进度。
实现的原理如下图:
在 main_thread 上创建子线程,用于执行长时间运行的程序。
子线程只负责给 main_thread(UI 线程)发消息,而不关心 GUI 的更新。
主线程响应子线程触发的事件,不如,更新 UI。
最简单的实现方式是,
子线程调用 wx.CallAfter(func, (args)) 注册新事件,并将 func 注册到新事件的处理句柄中。
新消息执行时,func 在主线程中执行并更新UI。
也可以自定义事件,自定义处理句柄。
sizer 内可以直接 Add(seizer), 像 Add 其他控件一样。
最终需要把主 sizer SetLayout 即可。