使用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代码不起作用?
答案 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-frame
(Window
)添加到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)