第 5 部分 · Objects & GUI
对象与界面
回答"对象怎么组织、界面怎么搭"。从 class 系统到第一个 GUI、控件、自定义绘制、声明式 GUI、后台任务。
面向对象——Racket 的 class 与对象
Racket 用 `(class object% ...)` 定义类,`new` 造对象,`send` 调方法。它是一套独立于函数式的对象系统,专门收拾那些“带着状态、长期存活”的家伙。
第一个 GUI——窗口、按钮与点击计数器
写 GUI 程序,本质就是三件事——开一个窗口、往里放几个控件、给控件挂上回调。可程序跑过 `show` 之后为什么不退出?按钮被点一下,又是怎么“自动”跑起一段代码的?
为什么 Racket GUI 写不出“现代界面”
Racket GUI 把控件一个个钉进窗口,事件交给鼠标命中的那个控件就结束——不冒泡、不组合。所以“一个任务项”这种现代 UI 的最小单元,用 `racket/gui` 怎么拼都拧巴。这不是你不会写,是它刻意选了另一条路。
8 种控件覆盖九成场景——按语义选 Racket GUI 控件
Racket 的 `racket/gui` 里,九成的界面靠 8 个控件类就搭得起来。选哪个,不取决于它长什么样,取决于用户要对它做什么。
Racket GUI 控件清单——内置库一次看全
`racket/gui` 自带一套跨平台桌面控件——窗口、面板、按钮、输入框、选择器、滑块、画布、菜单,`#lang racket/gui` 一声明就能用。这一篇按类别把常用控件过一遍清单。
自定义控件——子类化 canvas 自己画
内置控件到头了,`racket/gui` 把真正的出口留给 `canvas%`:自己拿绘图上下文画,自己接鼠标键盘事件。子类化一个画布,到底要重写哪几个方法?
gui-easy——声明式写 Racket GUI
Racket 自带的 `racket/gui` 是命令式的:建控件、注册回调、手动读写状态。gui-easy 在外面套了一层函数式壳——状态放进 Observable,界面用 View 声明,刷新由库接管。
GUI 不卡顿——把耗时任务挪到后台线程
点按钮卡死窗口,多半不是 Racket 慢,而是耗时任务跑错了线程——挪到后台线程,再用 `queue-callback` 或 `channel` 把结果递回去,窗口就不卡了。