JOptionPane"在容器中添加一个窗口" Clojure中的例外情况

时间:2016-10-12 15:28:46

标签: 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代码不起作用?

2 个答案:

答案 0 :(得分:1)

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)

您可以在您的repl中查看:

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-frameWindow)添加到Container,这会导致{{1} }}

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

IllegalArgumentException

这会导致clojure调用(javax.swing.JOptionPane/showInputDialog parent-frame "Hello?" "") ,并正确显示showInputDialog(Component parent, Object mess, String initialSelectionValue)

修改 您还可以为clojure可以选择正确方法的参数提供类型提示,如@James在其答案中提到的那样。这将是更好的方式。

JOptionPane

答案 1 :(得分:1)

如前所述,<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input type="checkbox" class="mod-link" name="selected" value="Blue" class="products">Blue <br> <input type="checkbox" class="mod-link" name="selected" value="Green" class="products">Green <br> <input type="checkbox" class="mod-link" name="selected" value="Purple" class="products">Purple <br> <div class="link-container"></div>已超载:

JOptionPane.showInputDialog

Java通过参数的数量及其类型来区分重载方法,但Clojure仅通过参数的数量来区分。您可以通过类型提示让Clojure调用正确的方法:

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

此处有更多信息:How do I call overloaded Java methods in Clojure