common-lisp - 如何等到事件结束后使用 ltk 从函数返回?
问题描述
我正在使用 ltk 为 Common-Lisp 中的 Dijkstra 算法开发 GUI 应用程序。但是,要将节点放置在画布上,我需要它的标签,为此,执行必须等到用户输入字符串(然后按 Return)才能使用此值启动节点实例。如果没有侦听过程,则在创建第二个顶层屏幕后立即返回。
下面是当用户在菜单上选择“添加节点”选项时执行的代码:
(defun node-add-mode (canvas)
(configure canvas :cursor "cross")
(bind canvas "<ButtonPress-1>"
(lambda (evt)
(let* ((pos-x (event-x evt))
(pos-y (event-y evt))
(data (read-node-data))
(node (make-instance 'node :pos (list pos-x pos-y) :data data)))
(populate-graph :node node)
(create-graph canvas *graph*)))))
该populate-graph
函数只是将创建的节点添加到实际图形中,然后该create-graph
函数将其绘制在画布上。这是read-node-data
我到目前为止实现的功能:
(defun read-node-data ()
(let* ((m (make-instance 'toplevel))
(f (make-instance 'frame :master m))
(l (make-instance 'label
:master f
:text "Insert The Object Value"))
(v (make-instance 'entry
:master f
:width *entry-width*)))
(wm-title m "Entry")
(pack f)
(pack l)
(pack v)
(bind v "<Return>"
(lambda (evt)
(let ((text (text v)))
(destroy m)
text)))))
我想仅在"<Return>"
事件发生后从该代码块返回条目文本,以便能够将其传递给节点实例化。
解决方案
Tcl 有一种vwait
机制来处理代码需要阻塞某个变量值的情况。据我所知,这在 LTK 中不可用。您可以使用另一个系统,例如cl-async
,但也许最简单的选择是将您的代码从里到外翻转,使其成为基于事件的:仅在知道名称时才构建节点。
(defun read-node-data (continuation)
...
(bind v
"<Return>"
(lambda (evt &aux (text (text evt)))
(destroy m)
(funcall continuation text))))
接着:
(defun node-add-mode (canvas)
(configure canvas :cursor "cross")
(bind canvas "<ButtonPress-1>"
(lambda (evt)
(let ((pos-x (event-x evt))
(pos-y (event-y evt)))
(read-node-data
(lambda (data)
(let ((node (make-instance 'node
:pos (list pos-x pos-y)
:data data)))
(populate-graph :node node)
(create-graph canvas *graph*))))))))
推荐阅读
- linux - Shell脚本 curl 检查远程位置问题的文件
- android - 通过启动器重新打开应用程序时,Chrome 自定义选项卡将关闭
- html - 图像在翻转时缩放和淡入淡出,以显示下面的文字
- javascript - 如何根据 React.js 中的计划选择(每月、每年)自动显示续订日期?
- xslt - xslt 创建一个计数器变量并打印结束值
- javascript - 图标淡入文本似乎面临问题
- javascript - 如何使用 webpack 将两个 js 文件合并为一个?
- django - Django 模型管理器
- sql - ORA-00922: 我的 APEX SQL 脚本中缺少或无效选项错误
- dataframe - 火花读取 csv 行为,其中文件在一种情况下包含标题,而没有用于休息的标题