Java “JOptionPane”;“将窗口添加到容器中”;Clojure中的例外

Java “JOptionPane”;“将窗口添加到容器中”;Clojure中的例外,java,clojure,Java,Clojure,使用JOptionPane.showInputDialog时,当我尝试指定父组件时,会得到一个IllegalArgumentException。它在Java中工作,但在Clojure中不工作。 不管异常是怎么说的,我实际上并没有在容器中添加窗口。我正在尝试创建一个单独的框架,并将其用作JOptionPane.showInputDialog的父窗口。这是我的Clojure代码: (def parent-frame (doto (new javax.swing.JFrame) (.set

使用
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父框架“Hello?”)
时,clojure似乎调用
showInputDialog(对象消息,对象初始选择值)

您可以在回复中检查此项:

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
允许将
对象作为消息传递。如果将
组件
作为消息传递,它将用作消息组件

在这种情况下,
父帧
作为消息传递,之后它试图将此
父帧
(即
窗口
)添加到
容器
,这导致了
非法argumentException

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

(javax.swing.JOptionPane/showInputDialog parent-frame "Hello?" "")
这将导致clojure调用
showInputDialog(组件父级、对象混乱、字符串初始选择值)
,并正确显示
JOptionPane

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

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

如前所述,
JOptionPane.showInputDialog
过载:

showInputDialog(Object message, Object initialSelectionValue)
showInputDialog(Component parentComp, Object message)
Java通过参数数量及其类型来区分重载方法,而Clojure仅通过参数数量来区分。您可以通过类型提示让Clojure调用正确的方法:

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

这里有更多信息:

对。Clojure和Java之间的区别在于Java通过参数数量及其类型来区分重载方法,而Clojure仅通过参数数量来区分。抢手货
(javax.swing.JOptionPane/showInputDialog #^java.awt.Component parent-frame "Hello?")