2016-10-12 5 views
3

JOptionPane.showInputDialog을 사용할 때 부모 구성 요소를 지정하려고하면 IllegalArgumentException이 표시됩니다. Java에서는 작동하지만 Clojure에서는 작동하지 않습니다. 예외가 있음에도 불구하고 실제로 컨테이너에 창을 추가하지는 않습니다. 별도의 프레임을 만들고이를 JOptionPane.showInputDialog의 부모 창으로 사용하려고합니다. 여기 내 Clojure의 코드는 다음과 같습니다JOptionPane 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 

:

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의 코드가 작동하지 않는 이유는 무엇입니까?

답변

1

JOptionPane.showInputDialog은 오버로드됩니다. 당신이 (javax.swing.JOptionPane/showInputDialog parent-frame "Hello?")을 실행하면

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

, 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 메시지로 전달되고, 나중에는 IllegalArgumentException 발생 Container로 ( Window이다)이 parent-frame를 추가하려고 시도.

대상 메서드가 오버로드 될 때 호출 할 메서드를 clojure가 결정하는 방법을 알지 못합니다. Clojure가 잘못된 것을 골랐다. 나는이 문제를 피하기 위해 다른 방법을 사용해야한다고 생각한다.

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

은 Clojure에서이 showInputDialog(Component parent, Object mess, String initialSelectionValue)를 호출 원인, 제대로 JOptionPane 표시됩니다.

또한 @ 제임스는 그의 대답에 언급 한 바와 같이 Clojure의 올바른 방법을 선택할 수 있음을 인수 타입 힌트를 제공 할 수 편집 할 수 있습니다. 이것은 더 나은 방법 일 것입니다.

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

오른쪽 :

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

여기에 자세한 내용이 있습니다.Clojure와 Java의 차이점은 Java가 오버로드 된 메소드와 매개 변수의 수를 구별하지만 Clojure는 매개 변수의 수만 구별한다는 점입니다. 좋은 캐치. –

1

으로 이미 JOptionPane.showInputDialog에 과부하가 명시된 :

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

자바는 매개 변수와 그 종류의 수에 의해 오버로드 된 메서드를 구분하지만, Clojure의 경우에만 매개 변수의 숫자로 구분합니다. 당신은 Clojure의 유형 힌트에 의해 적절한 방법을 호출 할 수 있습니다 : How do I call overloaded Java methods in Clojure