1. GUI
注意事项:XPCE 从 SWI-Prolog 9.x 起不再捆绑安装。生产项目优先考虑 Web UI 方案(见 c8)。本节当作概念入门,实际开发建议上 HTTP + HTML/JS 前端。
一句话概括:
new/2创建控件,send/2发消息,get/3取属性——XPCE 是 SWI-Prolog 自带的 GUI 工具箱。学完这章,你能用 XPCE 给 Prolog 程序加上图形界面——但你大概率不会用,因为 Web UI 才是更好的选择。 前置:Hello world | 难度:★ | 后续:—
一直写命令行程序不过瘾了?我也知道。
你写了一个解数独的 Prolog 程序(c9),每次都 ?- sudoku(Puzzle). 然后看文本输出。如果有人问你"能不能做个界面",你不可能说"Prolog 不能做 GUI"吧?
Prolog 能做。SWI-Prolog 自带一套 GUI 工具,叫 XPCE。
注意:XPCE 从 9.x 起不再随 SWI-Prolog 捆绑安装。它是老方案了——但这不意味着不该学。理解 XPCE 的概念(对象模型、事件、消息传递),以后再去看 Web UI(c8),一通百通。
1.1. 最简单的窗口
看看一个 Prolog 窗口长什么样:
:- use_module(library(pce)).
simple_window :-
new(D, dialog("Hello")),
send(D, append, new(T, text("Hello, XPCE!"))),
send(D, append, new(B, button("OK", message(@prolog, halt)))),
send(D, open).
跑一下:
?- simple_window.
一个窗口弹出来了。有文字,有按钮。点击 OK,程序退出。
就三行核心代码——new 创建,send 组装,open 显示。没有 HTML,没有 CSS,没有前端脚手架。
1.2. 核心操作:new、send、get
XPCE 世界里全是对象(PCE 类)。三个操作走天下:
1.2.1. new/2 — 创建
new(Dialog, dialog("Title")). % 窗口
new(Btn, button("Click")). % 按钮
new(Txt, text_item(name)). % 输入框
new(Lbl, label("Hello")). % 标签
new(Img, image('icon.png')). % 图片
1.2.2. send/2, send/3 — 操作
send(Obj, open). % 显示
send(Obj, destroy). % 销毁
send(Obj, append, Child). % 加子控件
send(Obj, set, X, Y, W, H). % 调位置大小
send(Obj, font, font(screen, roman, 14, normal)). % 改字体
1.2.3. get/3 — 读取
get(Txt, selection, Value). % 取输入框内容
get(Btn, displayed, Value). % 取显示状态
get(Dlg, width, W). % 取窗口宽度
1.3. 完整示例:计算器
理解了三个操作,就能写一个真正的 GUI 程序了:
:- use_module(library(pce)).
calculator :-
new(D, dialog("Calculator")),
new(Input, text_item(number, "")),
new(Result, label("")),
new(BtnAdd, button("+", message(@prolog, calc, Input, add, Result))),
new(BtnSub, button("-", message(@prolog, calc, Input, sub, Result))),
new(BtnMul, button("*", message(@prolog, calc, Input, mul, Result))),
new(BtnDiv, button("/", message(@prolog, calc, Input, div, Result))),
send(D, append, Input),
send(D, append, Result),
send(D, append, BtnAdd),
send(D, append, BtnSub),
send(D, append, BtnMul),
send(D, append, BtnDiv),
send(D, open).
calc(Input, Op, Result) :-
get(Input, selection, Val),
atom_number(Val, Num),
( Op == add -> Res is Num + Num
; Op == sub -> Res is Num - Num
; Op == mul -> Res is Num * Num
; Op == div -> Res is Num / Num
),
send(Result, selection, Res).
启动 calculator.,出来一个带输入框、结果显示、加减乘除按钮的窗口。
这还不是完整计算器——目前运算符只对同一个数操作。你可以扩展成带内存寄存器的版本试试。
1.4. 事件处理:message/@prolog
按钮按下去干什么?靠 message 对象:
send(Btn, message, message(@prolog, my_handler, Arg)).
@prolog 引用 Prolog 引擎本身——XPCE 通过它回调 Prolog 谓词。这是 Prolog 和 GUI 之间的桥梁。
看一个计数器例子:
:- dynamic counter/1.
counter(0).
counter_window :-
new(D, dialog("Counter")),
new(Lbl, label("Count: 0")),
new(Btn, button("+1", message(@prolog, inc, Lbl))),
send(D, append, Lbl),
send(D, append, Btn),
send(D, open).
inc(Lbl) :-
retract(counter(C)),
C1 is C + 1,
assert(counter(C1)),
send(Lbl, selection, C1).
每次点按钮,retract 取出当前值,+1 后 assert 回去,标签实时更新。纯 Prolog 驱动 UI 变化。
1.5. 常用控件一览
| 类 | 用途 | 创建示例 |
|---|---|---|
dialog |
窗口容器 | new(D, dialog("Title")) |
text_item |
输入框 | new(T, text_item(name)) |
label |
标签 | new(L, label("Text")) |
button |
按钮 | new(B, button("OK", message(...))) |
list_browser |
列表 | new(L, list_browser), send(L, append, item) |
menu |
下拉菜单 | new(M, menu(options)), send(M, append, choice) |
slider |
滑块 | new(S, slider(min, max, value)) |
image |
图片 | new(I, image('file.png')) |
graphical |
画布 | new(G, picture), send(G, display, Box) |
1.6. 画一个图
draw_canvas :-
new(P, picture("Canvas")),
new(Box, box(100, 50)),
send(Box, fill_pattern, colour(red)),
send(P, display, Box, point(50, 50)),
new(Circle, circle(40)),
send(Circle, fill_pattern, colour(blue)),
send(P, display, Circle, point(200, 50)),
send(P, open).
红方块,蓝圆——几行代码搞定图形渲染。
1.7. XPCE 的限制
坦白说,XPCE 不是面向未来的方案:
- 只在 SWI-Prolog 桌面版可用(Win/Linux/macOS)
- 不支持 Web 和移动端
- 没有可视化布局工具——全靠手写
send(..., append, ...) - 中文要手动设置字体
:- use_module(library(pce)).
:- initialization
new(D, dialog("测试")),
send(D, append, new(T, text("你好,世界!"))),
send(T, font, font(screen, song, 14, normal)),
send(D, open).
如果中文乱码,换成系统支持的字体(simsun、song 或其他 Unicode 字体)。
1.8. 下一步:Web UI
XPCE 适合快速原型和内部工具。生产环境要考虑 Web UI——用 Prolog 做后端,HTML/CSS/JS 做前端(c8 的路子)。
学会了 XPCE 的 new/send/get,再去看 HTTP 方案,概念上更顺畅——本质都是"Prolog 驱动界面",只是一个用本地窗口,一个用浏览器。
1.9. 总结
new/2创建控件send/2发送操作消息get/3读取控件属性message(@prolog, Pred, Args)绑定事件回调- 支持 dialog、按钮、输入框、列表、画布等常用组件
- 小场景比学一套 Web 前端省事——纯 Prolog 搞定前后端
1.10. 参考
- The Power of Prolog — GUI
- SWI-Prolog manual: XPCE