All Manuals > CAPI User Guide and Reference Manual > 7 Programming with CAPI Windows

7.5 Updating pane contents

Use only the documented functions such as the accessors (setf editor-pane-text) and (setf collection-items) and so on to set the data in a pane. For details, see the manual pages for the particular pane class and its superclasses in 21 CAPI Reference Entries.

7.5.1 Updating windows in real time

If your code needs to cause visible updates while continuing to do further computation, then you should run your computation in a separate thread which is not directly associated with the CAPI window.

Consider the following example where real work is represented by calls to sleep:

  1. Evaluate this code:
    (defun change-text (win text)
      (setf (title-pane-text win)
            text))
     
    (defun my-callback (win)
      (change-text win "Go")
      (loop
       for i from 0 to 20 do 
       (change-text win (format nil "~D" i))
       (sleep 0.1)))
     
    (defun test ()
      (let* ((p1 (make-instance 'title-pane
                                :text "init"))
             (p2 (make-instance
                  'button :text "Go"
                  :callback-type :none
                  :callback #'(lambda ()
                                (my-callback p1)))))
        (contain
         (make-instance 'row-layout :description (list p1 nil p2))
         :width 200 :height 200)))
    
  2. Run (test) and note that the updates do not appear until my-callback returns. This is because it uses only one thread.
  3. Now try this modified callback which uses a worker thread to perform the calculations:
    (defun my-work-function ()
      (let ((mbox (mp:ensure-process-mailbox)))
        ;; This should really have an error handler.
        (loop (let ((event (mp:process-read-event mbox
                            "Waiting for events")))
                (cond ((consp event)
                       (apply (car event) (cdr event)))
                      ((functionp event)
                       (funcall event)))))))
     
    (setf *worker*
          (mp:process-run-function "Worker process" ()
                                   'my-work-function))
     
    (defun change-text (win text)
      (apply-in-pane-process win
                             #'(setf title-pane-text)
                             text win))
     
    (defun my-callback (win)
      (mp:process-send
       *worker*
       #'(lambda ()
           (change-text win "Go")
           (loop
            for i from 0 to 20 do 
            (change-text win (format nil "~D" i))
            (sleep 0.1)))))
    
  4. Run (test) again: you should see the updates appear immediately.

A real application might also display an Abort button during the computation, with a callback that aborts the worker process.

Also see this example:

(example-edit-file "capi/elements/progress-bar-from-background-thread")

CAPI User Guide and Reference Manual (Unix version) - 01 Dec 2021 19:32:35