2016-10-12 4 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 

同等の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のコードが動作しない理由を任意のアイデアを?

答えて

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メッセージとして渡され、後でそれがIllegalArgumentExceptionを引き起こしContainerに(Windowである)このparent-frameを追加しようとしました。

ターゲットメソッドがオーバーロードされたときにどのメソッドを呼び出すかをclojureがどのように決定するのか分かりません。 Clojureは間違ったものを選んだ。私はあなたがこの問題を避けるために他の方法を使うべきだと思います。

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

これはClojureのはshowInputDialog(Component parent, Object mess, String initialSelectionValue)を呼び出し引き起こし、正しくJOptionPaneが表示されます。あなたはまた、Clojureのは、彼の答えで述べたよう@James正しい方法を選ぶことができると引数の型ヒントを提供することができます

EDIT 。これは良い方法でしょう。既に述べたよう

(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) 

Javaは、パラメータとその種類の数でオーバーロードされたメソッドを区別するが、Clojureのは、パラメータの数で区別されます。あなたはClojureのは、タイプヒンティングによって右メソッドを呼び出すために取得することができます:How do I call overloaded Java methods in Clojure

関連する問題