Как дождаться завершения события, чтобы вернуться из функции с помощью ltk? - PullRequest
3 голосов
/ 16 июня 2019

Я использую ltk для разработки приложения с графическим интерфейсом для алгоритма Дейкстры в Common-Lisp.Однако, чтобы разместить узел на холсте, мне нужна метка для него, и для этого выполнение должно ждать, пока пользователь не введет строку (и не нажмет 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>", чтобы иметь возможность передать егосоздание узла.

1 Ответ

2 голосов
/ 17 июня 2019

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