Anonymous class with JRuby


#1

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

but the code inside paint() didn’t run.

how can these be achieved?


#2

4wai wrote:

but the code inside paint() didn’t run.

how can these be achieved?

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.

  • Charlie

To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

#3

It works~
thanks alot

On Fri, Jun 5, 2009 at 3:21 AM, Charles Oliver N. <


#4

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)


#5

4wai wrote:

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:

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

  1. 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).

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