(def text-area (javax.swing.JTextArea.))
(def frame
(let [f (javax.swing.JFrame.)]
(.. f getContentPane (add text-area))
(.setMinimumSize f (java.awt.Dimension. 200 200))
(.setVisible f true)
f))
(def text-area-writer
(proxy [java.io.Writer] []
(close [])
(flush [])
(write [^chars chrs ^int offs ^int len]
(.append text-area (String. chrs offs len)))))
When I load the code above I get an "IllegalArgumentException: Unable
to resolve classname: int" so I think I'm not type hinting correctly.
Here is a similar piece of java code which works as expected:
public class Main extends JFrame {
private JTextArea text;
public Writer writer;
public Main() {
text = new JTextArea();
getContentPane().add(text);
setVisible(true);
setMinimumSize(new Dimension(200, 200));
writer = new TextAreaWriter();
}
class TextAreaWriter extends Writer {
public void close() throws IOException {}
public void flush() throws IOException {}
public void write(char[] chrs, int offs, int len) throws IOException {
String str = new String(chrs, offs, len);
text.append(str);
}
}
public static void main(String[] args) throws IOException {
Main m = new Main();
m.writer.write("Hello, World!");
}
}
Any help is much appreciated!
/Jonas
Indeed. You can't (in 1.2 at least) type hint "int" though you can
"ints" (array of int). Note that int is a primitive type while array
of int is a reference type.
Type hinting as Integer shouldn't throw exceptions, but you can
probably omit all but the chars hint and have the correct String
constructor overload selected.
Also note that while text area .append is safe to call from off the
EDT, other Swing methods mostly aren't, and it's something to watch
for if you do anything similar to this with other Swing components,
and wherever you construct your text area and its surrounds.
I tried with 1.3.0-alpha5. With type hints I get "CompilerException
java.lang.IllegalArgumentException: Only long and double primitives
are supported". If I only keep the ^chars hint I get an ArityException
when I do (.write text-area-writer "hello").
Is this problem unsolvable with proxy? Should I look into gen-class
and AOT compilation instead?
>
> Also note that while text area .append is safe to call from off the
> EDT, other Swing methods mostly aren't, and it's something to watch
> for if you do anything similar to this with other Swing components,
> and wherever you construct your text area and its surrounds.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
Does it work with 1.2? Where exactly is the ArityException being
thrown -- for what function or method?
It didn't work in 1.2 either. Here is some more info on the exception
thrown (this is with 1.3.0-alpha5)
user=> (.write text-area-writer "Hello, World!")
ArityException Wrong number of args (2) passed to: user$fn--38$fn
clojure.lang.AFn.throwArity (AFn.java\
:439)
user=> (pst)
ArityException Wrong number of args (2) passed to: user$fn--38$fn
user.proxy$java.io.Writer$0.write (:-1)
sun.reflect.NativeMethodAccessorImpl.invoke0
(NativeMethodAccessorImpl.java:-2)
sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke (Method.java:616)
clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:90)
clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:28)
user/eval47 (NO_SOURCE_FILE:4)
clojure.lang.Compiler.eval (Compiler.java:6223)
clojure.lang.Compiler.eval (Compiler.java:6190)
clojure.core/eval (core.clj:2680)
clojure.main/repl/read-eval-print--5617 (main.clj:180)
nil
user=>
Thanks for helping out with this Ken!
The proxy documentation says
If a method fn is not provided for a class method, the superclass
methd will be called.
This doesn't seem to work if you override one of several overloads of
a method. The documentation should probably be clarified to reflect
that this isn't the case for overloads of a method you have
overridden; it seems you have to supply one function (overloaded for
arity) that implements all of the overloads, as that one function will
be called for all of the overloads.
This proxy works:
(proxy [java.io.Writer] []
(close [])
(flush [])
(write
([chrs offs len]
(if (string? chrs)
(.append text-area (subs chrs offs (+ offs len)))
(.append text-area (String. ^chars chrs offs len))))
([thing]
(.append text-area (str thing))))))
The second arity handles all the overloaded .write methods with only
one parameter, and the first handles the String offset length and
Char-Array offset length overloads.
> Thanks for helping out with this Ken!
You're welcome.