Java interop question: proxy or gen-class?

71 views
Skip to first unread message

Gregg Williams

unread,
Apr 9, 2010, 11:54:03 PM4/9/10
to Clojure
Hi--I'm continuing on my path to learning how to use Clojure with the
graphics library Piccolo2D (http://
www.piccolo2d.org) by re-implementing some of Piccolo2D's sample
programs. This time, I'm working on the "Building the Interface"
program described at http://www.piccolo2d.org/learn/interface.html.

I've used proxy successfully several times so far, but I'm not sure I
can use it here. The code that I'm trying to translate is as follows:

-----------------------------------
class ToggleShape extends PPath {

private boolean fIsPressed = false;

public ToggleShape() {
setPathToEllipse(0, 0, 100, 80);

addInputEventListener(new PBasicInputEventHandler() {
public void mousePressed(PInputEvent event) {
super.mousePressed(event);
fIsPressed = true;
repaint();
}
public void mouseReleased(PInputEvent event) {
super.mouseReleased(event);
fIsPressed = false;
repaint();
}
});
}

protected void paint(PPaintContext paintContext) {
if (fIsPressed) {
Graphics2D g2 = paintContext.getGraphics();
g2.setPaint(getPaint());
g2.fill(getBoundsReference());
} else {
super.paint(paintContext);
}
}
}
-----------------------------------

Some questions:

1) Because this new class, ToggleShape, has the added state of
fIsPressed, is it possible to use proxy at all, or do I have to use
gen-class? If it's the latter, how do I declare the namespace that
surrounds the gen-class so that this new class is visible to the code
that uses it?

2) If I can use proxy, do I create a constructor for this nameless new
class by redefining PPath (which is, after all, the name of the
constructor for the superclass)?

As always, thanks for your help.

Per Vognsen

unread,
Apr 10, 2010, 12:43:56 AM4/10/10
to clo...@googlegroups.com
On Sat, Apr 10, 2010 at 10:54 AM, Gregg Williams <gre...@innerpaths.net> wrote:
> Because this new class, ToggleShape, has the added state of
> fIsPressed, is it possible to use proxy at all

The proxy body can close over the lexical scope:

(let [pressed? (ref false)]
(proxy [PPath] []
;; ...
(ref-set pressed? true) ;; write ref
@pressed? ;; read ref
;; ...
))

-Per

Gregg Williams

unread,
Apr 14, 2010, 1:53:54 AM4/14/10
to Clojure
Since my last post, I've implemented and successfully run everything
in this sample program except the ToggleShape class, and I absolutely
cannot figure out how to use proxy correctly. Here's the Java code
that I'm trying to re-create in Clojure:

class ToggleShape extends PPath {
private static final long serialVersionUID = 1L;


private boolean fIsPressed = false;

public ToggleShape() { ; location (1)
<<<<<<<<<<<<<<<<<<<<<
setPathToEllipse(0, 0, 100, 80);

addInputEventListener(new PBasicInputEventHandler() {
public void mousePressed(final PInputEvent event) {


super.mousePressed(event);
fIsPressed = true;
repaint();
}

public void mouseReleased(final PInputEvent event) {


super.mouseReleased(event);
fIsPressed = false;
repaint();
}
});
}

protected void paint(final PPaintContext paintContext) {
if (fIsPressed) {
final Graphics2D g2 = paintContext.getGraphics();
g2.setPaint(getPaint());
g2.fill(getBoundsReference());
}
else {
super.paint(paintContext);
}
}
}


Note that this subclass, ToggleShape, redefines its constructor (see
the line marked "location (1)", above). The question is, what name do
I put to the function that executes the Clojure equivalent of
"setPathToEllipse(0, 0, 100, 80)"? Since proxy creates an anonymous
subclass, the only function named that I could think to use is that of
its superclass, PPath--but I can't get it to work (and the code below
is just one of several variations I've tried).

To eliminate other possible sources of error, I've taken out the event
listeners in the Clojure code below, and all I'm trying to do is have
the program display the %$#@#! ellipse (I can get it to display a
square just fine). I've also put a println statement in the code that
creates an instance of ToggleShape (which does execute), and another
println statement in the code that implements ToggleShape (which DOES
NOT execute).

I've searched the web for articles and source code that might give me
some idea of how to proceed, and I've also consulted Java reference
books, but I haven't found anything that explains what I need to do.
Anyway, here's one version of the corresponding Clojure code:

(defn create-toggle-shape
"Creates an ellipse that changes shape when it is clicked."
[]
(let [fIsPressed? (ref false)
serialVersionUID (long 1)]
(proxy [PPath] [] ; ToggleShape is an extension of PPath

; I'm trying to create the constructor for ToggleShape--proxy
; requires that what follows is a sequence of superclass method-
names-
; arguments-and-bodies. What do I call it here? Since the
superclass is
; PPath, the name of its constructor is PPath, so that's what
I'm
; trying here--but it doesn't seem to work: the println is
; never executed.
(PPath [] ;
; super's constructor should execute automatically
(println "Reached ToggleShape")
(.setPathToEllipse 0 0 100 80)
;add input listeners here
)

(paint [paintContext]
(if (fIsPressed?)
(let [g2 (.getGraphics paintContext)]
(do
(.. g2 setPaint getPaint)
(.fill g2 (.getBoundsReference this))))
(proxy-super paint paintContext))))))

I can post the entire program if anyone wants to see it. As always,
thanks for taking the time to help.

Meikel Brandmeyer

unread,
Apr 14, 2010, 3:29:35 AM4/14/10
to Clojure
Hi,

My try. Not tested, though...

(defn create-toggle-shape
"Creates an ellipse that changes shape when it is clicked."
[]

(let [fIsPressed? (atom false)
shape (proxy [PPath] []
(paint
[#^PPaintContext paintContext]
(if @fIsPressed?
(doto (.getGraphics paintContext)
(.setPaint (.getPaint this))
(.fill (.getBoundReference this)))
(proxy-super paint paintContext))))]
(doto shape


(.setPathToEllipse 0 0 100 80)

(.addInputEventListener
(proxy [PBasicInputEventHandler] []
(mousePressed
[evt]
(proxy-super mousePressed evt)
(reset! fIsPressed? true)
(.repaint shape))
(mouseReleased
[evt]
(proxy-super mouseReleased evt)
(reset! fIsPressed? false)
(.repaint shape)))))))

Sincerely
Meikel

Gregg Williams

unread,
Apr 16, 2010, 11:52:20 PM4/16/10
to Clojure
Many thanks to Meikel Brandmeyer, whose code (after a one-character
typo correction) worked the first time. As soon as I saw it, I
understood every line of it; the problem was, it wouldn't have
occurred to me to put all those elements (which, individually, I
understood) together in just that way. Meikel, thanks again for
contributing to a frustrated newcomer's education.

By the way, I recommend comparing the original Java source code to the
final version (at http://gist.github.com/369239) to any newcomer who
wants to learn how to write Java code within a Clojure program--you
don't even have to be interested in Piccolo2D to learn from this. (May
you have) Good coding!

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

Kevin

unread,
Apr 17, 2010, 11:50:47 AM4/17/10
to clo...@googlegroups.com
> Many thanks to Meikel Brandmeyer, whose code (after a one-character typo
correction) worked the first time. As soon as I saw it, I understood every
line of it; the problem was, it wouldn't have occurred to me to put all
those elements (which, individually, I understood) together in just that
way. Meikel, thanks again for contributing to a frustrated newcomer's
education.
>
> By the way, I recommend comparing the original Java source code to the
final version (at http://gist.github.com/369239) to any newcomer who wants
to learn how to write Java code within a Clojure program--you don't even
have to be interested in Piccolo2D to learn from this. (May you have) Good
coding!

Nice, thanks for posting your efforts with this. Piccolo's zoomable UI
is pretty interesting, and I've been wanting to play with it for quite a
while. Too many other projects; I hadn't taken the time to go into it.

Putting it together with Clojure, and having a nice little sample of it
to try out, brings it closer to the front of the line for me. Much
appreciated!


Kevin Kelley
Reply all
Reply to author
Forward
0 new messages