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).

如果中文乱码,换成系统支持的字体(simsunsong 或其他 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. 参考

Copyright © zhzluke96 2020 all right reserved,powered by Gitbook该文件修订时间: 2026-06-30 16:08

results matching ""

    No results matching ""