当前位置: 首页 > 知识库问答 >
问题:

Leiningen下Clojure UI应用程序中AWT异常的跟踪

赵高韵
2023-03-14

关于Clojure中第一个UI程序的SO问题,我创建了一个新的leiningen应用程序项目:

lein new app a-ui-app
(defn -main
  "See https://stackoverflow.com/questions/2792451/improving-my-first-clojure-program?rq=1."
  [& args]
  ;; work around dangerous default behaviour in Clojure
  (alter-var-root #'*read-eval* (constantly false))

  (doto panel
        (.setFocusable true)
        (.addKeyListener panel))

  (doto frame
        (.add panel)
        (.pack)
        (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
        (.setVisible true))

  (loop []
        (draw-rectangle panel @x @y)
        (Thread/sleep 10)
        (recur))
  )
lein run
lein uberjar
java -jar ./target/a-ui-app-0.1.0-SNAPSHOT-standalone.jar 

线程“Awt-EventQueue-0”java.lang.IllegalArgumentException中出现异常:没有匹配子句:在a_ui_app.core处的157$FN__16$FN__21$FN__22处的Invoke(core.clj:19)在clojure.lang.afn.call(afn.java:18)在clojure.lang.lockingTransaction.run(lockingTransaction.java:263)在clojure.lang.lockingTransaction.runinTransaction(lockingTransaction.java:231)在

我没有对project.clj做任何更改--只是使用了Leiningen生成的一个。

我想知道是怎么回事。我对Java线程并不了解。问题是否与leiningen启动应用程序Java线程的方式有关?是无法避免的吗?如果不是,我该如何修复它,无论是对于这个小示例程序,还是作为使用UI线程的未来项目的项目模式(我认为它是awt-eventqueue-0)。

共有1个答案

田宇
2023-03-14

我不知道为什么你会准确地得到那个错误,但我得说你做错了几件事:秋千是一个复杂的野兽;)

Swing不是线程安全的。关于在EDT(事件调度线程/UI线程)上可以做什么和不能做什么的“规则”随着时间的推移而改变...在某个时候,Sun决定修改Swing组件的所有操作都应该在EDT上完成。

因此,从另一个线程绘制您的矩形,忙着做一个旋转循环是一个很大的禁忌。此外,您绘制图形的方式也不正确:您不应该直接从其他线程获取图形对象并修改它(这是一种超级黑客,应该会触发疯狂的闪烁)。一种“正确”的Swing方法是重写PaintComponent(GraphicsG)Java方法并在那里进行绘制:因此每次需要重绘组件时,都会正确地重绘它。

(import java.awt.Color)
(import java.awt.Dimension)
(import java.awt.event.KeyListener)
(import javax.swing.JFrame)
(import javax.swing.JPanel)

(def x (ref 0))
(def y (ref 0))

(def panel
  (proxy [JPanel KeyListener] []
    (paintComponent [g]
      (proxy-super paintComponent g)
      (doto g
        (.setColor (java.awt.Color/WHITE))
        (.fillRect 0 0 100 100)
        (.setColor (java.awt.Color/BLUE))
        (.fillRect (* 10 @x) (* 10 @y) 10 10)))
    (getPreferredSize [] (Dimension. 100 100))
    (keyPressed [e]
      (let [keyCode (.getKeyCode e)]
        (if (== 37 keyCode) (dosync (alter x dec))
        (if (== 38 keyCode) (dosync (alter y dec))
        (if (== 39 keyCode) (dosync (alter x inc))
        (if (== 40 keyCode) (dosync (alter y inc))))))
        (.repaint this)
        ))
    (keyReleased [e])
    (keyTyped [e])))

(def frame (JFrame. "Test"))

(defn -main [& args]

  (doto panel
        (.setFocusable true)
        (.addKeyListener panel))

  (doto frame
        (.add panel)
        (.pack)
        (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
        (.setVisible true)))

我不是deref'的粉丝,但是paintcomponent和key listener触发器都保证在EDT上发生,所以在您的情况下读数应该是一致的。如果我是你,我仍然会使用一个xydef。

对于JPanel(它也是一个KeyListener)和-main函数(它将KeyListener添加到自己的),我也有点困惑:(doto panel(.addkeylistener panel))感觉很奇怪。可能还可以,我不知道:只是感觉怪怪的:)

关于您的异常,我不知道,但是Swing EDT实际上偶尔会抛出异常,因为Swing有相当多的bug,而且Swing的正确使用是如此复杂,以至于程序往往会犯相当多的错误。根据平台/JVM,要么捕获异常并使EDT继续运行,要么自动启动一个新的EDT。通常情况下,您不应该能够“崩溃”EDT,因为如果EDT崩溃,它应该自动重新启动。这就是为什么你看到了例外,却又说你的程序仍然“工作得很好”的原因。

我想说,这个异常和神秘的堆栈跟踪与Swing不是线程安全的有关,并且您做了一些奇怪的事情:旋转循环,获取面板的底层图形对象,然后搞乱它,但我真的不确定。

经过上述修改的代码似乎正在精细地、毫不眨眼地执行您想要执行的操作。

希望有帮助。

 类似资料:
  • 问题内容: 我正在使用GWT RPC和Hibernate使用Eclipse环境从MySQL插入和检索数据。我已经在服务接口中编写了两种方法来从单个MySQL表插入和检索数据。 该程序运行正常,但引发了此异常。 ServiceImpl类: 入口点类: 问题答案: 您的意思是您的代码工作正常,但您在日志中看到此异常?异常基本上意味着编译缓存由于某种原因无法加载。高速缓存很可能由于某种原因已损坏,因此请

  • 出于某种原因,这段代码给出了标题中给出的错误,然后是大量异常列表。然后控制台会加载,但不会加载任何数据,您必须将鼠标悬停在控制台的每个部分上才能让它显示出来。有什么帮助吗? 编辑:以下是例外:

  • 问题内容: 我正在开发一个带有执行自定义绘画的组件的Swing应用程序。当我在绘画代码中犯了一些错误并引发异常时,这种情况很难调试。不会被调试器捕获,而是显示带有异常信息的弹出窗口。此外,线程似乎已重新启动,并且由于编码错误而导致异常,因此该线程一次又一次地显示出来。 当我有幸切换到调试器时(这很困难,因为随着应用程序收到绘画请求,越来越多的弹出窗口不断出现),调试控制台会向我显示异常信息,例如:

  • 我正在尝试将文件读取到中,但它提供了一些异常。我正在使用POI库。我该怎么办?请帮帮我。这是我的代码: 这是:

  • 我试图创建一个应用程序,但我一直遇到相同的运行时异常。我已经和它斗争了好几天,我不知道如何修复它。任何建议都将不胜感激!这是我在Java中的第一个相当长的项目,所以我决心解决它;只是有相当多的麻烦,我不知道如何克服这一点。

  • 我正在用VSCode中的C#编写一个语音到文本的模型。模型正确地转录了第一个文件。当我添加新文件并尝试转录时,出现以下错误: 发生异常:CLR/System。ApplicationException类型为“System”的异常。系统中发生ApplicationException“”。私有的CoreLib。dll,但未在Microsoft的用户代码中处理:“异常,错误代码:0x8(SPXERR\u文