当我开始尝试 Common Lisp GUI 编程包时,我总是在很早的阶段就遇到问题。我正在将 SBCL 2.1.1 和 2.3.8 与 Debian“Bullseye”一起使用,目前,我想通过 LTk 示例了解其用法。
(with-nodgui())中的hello world例子是没有问题的。然而,如果谈到“第一个(真实的)例子”,从
开始(wm-title *tk* "Feet to Metres")
我最终在调试器中遇到了本文主题中提到的情况(在 Slime 中,例如在 shell 中)。
您可以很容易地认识到我与专家相反,因为此类错误消息总是压倒我寻找起点寻找原因的能力。
当我尝试编译以下不带 WM-TITLE 的 LET 形式的示例时
(let ((content (make-instance 'frame)))
(...))
错误消息保持不变。
您可以给我提示如何避免吗?这对我来说是一份提前的圣诞礼物。
(通过尝试 CLisp,我几乎要“交叉检查”SBCL 的刚性是否存在问题。但我必须意识到,因此我必须参与一些用于设置 CLisp 的初始配置工作,因为它没有”不想快速加载:nodgui 开箱即用,更不用说找到 ASDF ...而且我真的(!)不想打开一个新的烦人的[一个posteriori微小]问题区域。我只是想要按照示例来设计我想要的 GUI,而不是在不知道为什么的情况下最终进入调试器 - 让我哭泣......并且我想使用 SBCL 来做到这一点)
致以诚挚的问候
P.S.:关注回溯可能会有所帮助 - 但不幸的是,在这个级别上不适合我。
Backtrace:
0: ((FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN FLUSH-WISH))
1: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))
2: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK #<FUNCTION (FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN FLUSH-WISH) {53B59E7B}> #<SB-THREAD:MUTEX "Anonymous recursive lock" taken owner=worker> T NIL)
3: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))
4: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK #<FUNCTION (FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN NODGUI::SEND-WISH) {7F325273612B}> #<SB-THREAD:MUTEX "Anonymous recursive lock" taken owner=worker> T NIL..
5: (NODGUI::SEND-WISH "wm title . {Feet to Metres}")
Locals:
#:ITEM = "wm title . {Feet to Metres}"
6: ((:METHOD WM-TITLE (WIDGET T)) #<WIDGET {10079B22E3}> "Feet to Metres") [fast-method]
Locals:
TITLE = "Feet to Metres"
NODGUI::W = #<WIDGET {10079B22E3}>
7: (SB-INT:SIMPLE-EVAL-IN-LEXENV (WM-TITLE *TK* "Feet to Metres") #<NULL-LEXENV>)
8: (EVAL (WM-TITLE *TK* "Feet to Metres"))
9: ((LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL))
10: (SWANK::CALL-WITH-RETRY-RESTART "Retry SLIME interactive evaluation request." #<FUNCTION (LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL) {1008258DAB}>)
11: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<FUNCTION (LAMBDA NIL :IN SWANK:INTERACTIVE-EVAL) {1008258D8B}>)
Locals:
FUN = #<FUNCTION (LAMBDA () :IN SWANK:INTERACTIVE-EVAL) {1008258D8B}>
PACKAGE = NIL
12: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")") #<NULL-LEXENV>)
13: (EVAL (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")"))
14: (SWANK:EVAL-FOR-EMACS (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")") "COMMON-LISP-USER" 38)
Locals:
BUFFER-PACKAGE = "COMMON-LISP-USER"
CONDITION = #<TYPE-ERROR expected-type: STREAM datum: NIL>
FORM = (SWANK:INTERACTIVE-EVAL "(wm-title *tk* \"Feet to Metres\")")
ID = 38
OK = NIL
RESULT = NIL
15: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
[No Locals]
16: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNCTION (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {539F452B}>)
17: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/home/old/jochen/Desktop/Arbeit/Akademisch/Forschung/Grundlagen/Lisp/slime-4-atom/slime/swank/sbcl.lisp") #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNC..
18: (SWANK::CALL-WITH-BINDINGS ((*STANDARD-INPUT* . #<SWANK/GRAY::SLIME-INPUT-STREAM {10018609B3}>)) #<FUNCTION (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {539F47DB}>)
19: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
20: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN))
21: ((FLET "WITHOUT-INTERRUPTS-BODY-174" :IN SB-THREAD::RUN))
22: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN))
23: ((FLET "WITHOUT-INTERRUPTS-BODY-167" :IN SB-THREAD::RUN))
24: (SB-THREAD::RUN)
25: ("foreign function: call_into_lisp_")
26: ("foreign function: funcall1")
也许这就是你加载所有东西的方式。让我们从头开始:
(defpackage :feet-to-meter
(:use :cl :nodgui))
(in-package :feet-to-meter)
(defun feet-to-meter ()
(with-nodgui ()
(wm-title *tk* "Feet to Metres") ; 1
(let ((content (make-instance 'frame))) ; 2
(configure content :padding "3 3 12 12") ; 3
(grid content 0 0 :sticky "nsew")
(grid-columnconfigure *tk* 0 :weight 1)
(grid-rowconfigure *tk* 0 :weight 1)
(let* ((feet-entry (make-instance 'entry :master content :width 7)) ; 4
(metres-label (make-instance 'label :master content :text "")))
(flet ((calculate () ; 5
(let ((feet (read-from-string (text feet-entry))))
(setf (text metres-label)
(if (numberp feet)
(/ (round (* 0.3048 feet 10000.0)) 10000.0)
"")))))
; top row has the entry widget and explanatory label to its right
(grid feet-entry 1 2 :sticky "we" :padx 5 :pady 5) ; 6
(grid (make-instance 'label :master content :text "feet")
1 3 :sticky "w" :padx 5 :pady 5)
; middle row has three labels
(grid (make-instance 'label :master content :text "is equivalent to")
2 1 :sticky "e" :padx 5 :pady 5)
(grid metres-label 2 2 :sticky "we" :padx 5 :pady 5)
(grid (make-instance 'label :master content :text "metres")
2 3 :sticky "w" :padx 5 :pady 5)
; last row has the button on right
(grid (make-instance 'button :master content ; 7
:text "Calculate"
:command #'calculate)
3 3 :sticky "w" :padx 5 :pady 5)
(focus feet-entry) ; 8
(bind *tk* "<Return>" (lambda (evt) (calculate))))))
))
尝试一下:
英尺到米>(英尺到米)