-
Notifications
You must be signed in to change notification settings - Fork 94
Java Reflection
Some people think java reflection is cool (they are mistaken, it is not is a pain), where possible avoid using it at all costs, unfortunately some of the processing guys seem to think it is cool, so they have contaminated the processing api with it. Fortunately there are often ways to avoid it (and sometimes come up with something that is more appropriate for use in a ruby environment). One such example is the thread
convenience method of processing, that relies on reflection to allow you to pass a function to a thread.
// in java processing
thread("someFunction");
void someFunction(){
do stuff..
}
In ruby-processing we have overridden the thread convenience method to be much more ruby like (in keeping with ruby Thread, whilst actually using a java thread under hood) to take a block.
# in ruby-processing
thread do
some stuff..
end
Actually we don't really need this convenience function in ruby-processing we've just overridden it to prevent any confusion, it is just as easy to use the existing Thread syntax...
# natively available with jruby
Thread.new do
some stuff..
end
Another example where we can do better in ruby-processing, is in a replacement for the selectInput
convenience method. This method also relies on reflection, and is now deprecated in ruby-processing ( and probably wouldn't work anyway ). See the file_chooser library, which uses JFileChooser under the hood, but we have created a more capable chooser (easy setup of file filters), and a much more ruby-like experience, with block encapsulation. You could of course roll your own file chooser implementation, if you create something better please let us know.
A further example where reflection gets pressed into action ( in vanilla processing ) is the recommended way that you registerMethods
with the processing Applet from a processing library, this is done using reflection as follows
// in java processing
public BasicLibrary(PApplet parent) {
this.parent = parent;
parent.registerMethod("dispose", this);
}
public void dispose() {
// Anything in here will be called automatically when
// the parent sketch shuts down. For instance, this might
// shut down a thread used by this library.
}
You have to go through hoops to replicate this in ruby but it can be done:-
# in ruby-processing using reflection
require 'jruby/core_ext'
class TestRegister
attr_reader :parent
def initialize parent
@parent = parent
register = parent.java_method :registerMethod, [Java::JavaLang::String, java.lang.Object]
register.call(:draw, self)
register.call(:pre, self)
end
def pre
puts "before draw"
parent.background(100)
end
def draw
puts "at begin draw"
parent.fill(200, 100)
parent.ellipse(100, 100, 60, 60)
end
end
cls = TestRegister.become_java!
The magic in the last line ensures that the TestRegister class becomes java, so that when you pass self, it is a java.lang.Object
. And believe it or not this actually works see following sketch:-
# test class ruby-processing
load "./register.rb"
def setup
size 200, 200
fred = TestRegister.new self
no_loop
end
def draw
fill(0, 0, 200)
ellipse(120, 120, 60, 60)
end
Anyone who can get registerMethod("mouseEvent")
or registerMethod("keyEvent")
to actually work in ruby-processing might find this useful, please be kind enough to let us know how you got it to work!!!
I have just created ArcBall (mouse drag to rotate and mousewheel zoom) functionality for ruby processing see JRubyArt development branch for details. I did this by writing a jruby java extension, this may well be the way forward to use the reflection capabilities built into processing pre(), post(), draw(), etc. Creating the ArcBall extension is written up in RVecMath repository.