Hi all,
I have some questions about anonymous class with JRuby.
I want to have some code like
JPanel p = new JPanel() {
public void paint(Graphics g) {
//draw something
}
};
new JFrame().getContentPane().add( p);
with JRuby
I try
p = JPanel.new
def p.paint(g)
//draw something
end
JFrame.new.getContentPane.add p
Because the JPanel has its own paint method, by the time you’ve
constructed it here it’s already too late to replace it. Java won’t see
anything we add after the fact. I think this would work:
p = Class.new(JPanel) do
def paint(g) … end
end.new
Since now you’re explicitly creating a new subclass and overriding paint
from the parent.
I’ve got another problem, seems the paint method cannot access the
variable
outside
img = BufferedImage.new
panel = Class.new JPanel do
def paint (g)
g.drawImage img, 0, 0, nil
end
end.new
When the panel paint method is called, a exception throws
Exception in thread “AWT-EventQueue-0” alarm.rb:27:in paint': undefined local variable or methodimg’ for #<#Class:01x51f266:0x88884e>
(NameError)
from :1
…internal jruby stack elided…
from #Class:01x51f266.paint(:1)
from (unknown).(unknown)(:1)
I’ve got another problem, seems the paint method cannot access the
variable outside
img = BufferedImage.new
panel = Class.new JPanel do
def paint (g)
g.drawImage img, 0, 0, nil
end
end.new
Ok, you can do one of three things:
store the image in a constant
This would allow it to be accessed from your method and would have
little to no perf impact on the code. But of course ideally your img
would be a constant value. Alternatively you could store it into an
instance variable of some constant-referenced container.
Depending on how likely you are to need to replace/re-set img, this may
or may not be an option.
use define_method
img = BufferedImage.new
panel = Class.new JPanel do
define_method :paint do |g|
g.drawImage img, 0, 0, nil
end
end.new
Because you’re using all blocks here, the outer img variable will be
visible to the define_method version of paint. The down side is that
define_method tends to have reduced performance compared to a normal
method (for now…we have some ideas on how to improve it).
just define a real class and put the value into it
This is probably the cleanest option. Just define this JPanel subclass
elsewhere as a real named class and pass the img into its constructor or
into an attribute writer. Then use it as a normal ivar.
Charlie
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.