java - Clojure 中的 JOptionPane "adding a window to a container"异常

标签 java clojure

在使用 JOptionPane.showInputDialog 时,我在尝试指定父组件时遇到了 IllegalArgumentException。它适用于 Java 但不适用于 Clojure。 不管异常怎么说,我实际上并没有向容器添加窗口。我正在尝试创建一个单独的框架并将其用作 JOptionPane.showInputDialog 的父窗口。这是我的 Clojure 代码:

(def parent-frame
  (doto (new javax.swing.JFrame)
    (.setDefaultCloseOperation javax.swing.JFrame/DISPOSE_ON_CLOSE)
    (.pack)
    (.setVisible true)))
(javax.swing.JOptionPane/showMessageDialog parent-frame "Hello") ;pops up dialog
(javax.swing.JOptionPane/showInputDialog parent-frame "Hello?")  ;throws an exception

等效的 Java 代码符合我的预期:

JFrame parentFrame = new JFrame();
parentFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
parentFrame.pack();
parentFrame.setVisible(true);
JOptionPane.showMessageDialog(parentFrame,"Hello"); //pops up a dialog
JOptionPane.showInputDialog(parentFrame,"Hello?");  //pops up a dialog

知道为什么 Clojure 代码不起作用吗?

最佳答案

JOptionPane.showInputDialog 已过载。

showInputDialog(Object message, Object initialSelectionValue)
...
showInputDialog(Component parentComp, Object message)

当您执行 (javax.swing.JOptionPane/showInputDialog parent-frame "Hello?") 时,clojure 似乎调用了 showInputDialog(Object message, Object initialSelectionValue) .

你可以在你的回复中检查这个:

user=> (javax.swing.JOptionPane/showInputDialog parent-frame "hello")

IllegalArgumentException adding a window to a container  java.awt.Container.checkNotAWindow (Container.java:490)
user=> *e
#error {
 :cause "adding a window to a container"
 :via
 [{:type java.lang.IllegalArgumentException
   :message "adding a window to a container"
   :at [java.awt.Container checkNotAWindow "Container.java" 490]}]
 :trace
 [[java.awt.Container checkNotAWindow "Container.java" 490]
  [java.awt.Container addImpl "Container.java" 1091]
  [java.awt.Container add "Container.java" 973]
  [javax.swing.plaf.basic.BasicOptionPaneUI addMessageComponents "BasicOptionPaneUI.java" 358]
  [com.apple.laf.AquaOptionPaneUI createMessageArea "AquaOptionPaneUI.java" 92]
  [javax.swing.plaf.basic.BasicOptionPaneUI installComponents "BasicOptionPaneUI.java" 172]
  [javax.swing.plaf.basic.BasicOptionPaneUI installUI "BasicOptionPaneUI.java" 141]
  [javax.swing.JComponent setUI "JComponent.java" 666]
  [javax.swing.JOptionPane setUI "JOptionPane.java" 1860]
  [javax.swing.JOptionPane updateUI "JOptionPane.java" 1882]
  [javax.swing.JOptionPane <init> "JOptionPane.java" 1845]
  [javax.swing.JOptionPane showInputDialog "JOptionPane.java" 568]
  [javax.swing.JOptionPane showInputDialog "JOptionPane.java" 494]
  [javax.swing.JOptionPane showInputDialog "JOptionPane.java" 455]
  [user$eval10619 invokeStatic "form-init4926112649336753943.clj" 1]
  [user$eval10619 invoke "form-init4926112649336753943.clj" 1]
  ...

如果您检查JOptionPane 的源代码并检查第 455 行,

public static String showInputDialog(Object message, Object initialSelectionValue) {
    return showInputDialog(null, message, initialSelectionValue); // <= Line 455
}

如您所见,JOptionPane 允许将 Object 作为消息传递。如果您将 Component 作为消息传递,它将用作消息组件。

在这种情况下,parent-frame 作为消息传递,稍后它尝试添加此 parent-frame(即 Window ) 到 Container,这导致了 IllegalArgumentException

我不知道clojure在重载目标方法时如何决定调用哪个方法。 Clojure 选错了一个。我认为你应该使用其他方法来避免这个问题。

(javax.swing.JOptionPane/showInputDialog parent-frame "Hello?" "")

这将导致 clojure 调用 showInputDialog(Component parent, Object mess, String initialSelectionValue),并正确显示 JOptionPane

编辑 您还可以为 clojure 可以选择正确方法的参数提供类型提示,正如@James 在他的回答中提到的那样。这是更好的方法。

(javax.swing.JOptionPane/showInputDialog #^java.awt.Component parent-frame "Hello?")

关于java - Clojure 中的 JOptionPane "adding a window to a container"异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40002537/

相关文章:

java - 在构造函数中初始化的模拟依赖项

clojure - Om Next 的 query->ast 和 ast->query 函数

java - 如何在 Java 或 Clojure 中用正则表达式替换字符串

maven-2 - 如何在没有 clojure.jar 的情况下从 Github 存储库在 Ubuntu 10.04 上安装 Clojure

vector - Clojure HashMap 作为广义向量

java - 如何让一帧显示50次1秒,每次显示就消失

java - 当 json 中的键之一包含值列表时,使用 Retrofit 将 JSON 键值对转换为 Java 对象

java - Dozer 无法将 Hibernate 的 persistentBag 映射到 List

Clojure.spec:如何规范对随机变化敏感的数据结构?

java - Ant资源存在检查