JRuby: Instance/Object method ovveride on a JPanel fails?

With the caveat I’m new to JRuby but have 20 years of software
experience:

I like when learning a new language to play around with how to do
things. So in one case I did the two standard java idioms in JRuby to
display an image [methods dispaly and display2], and then decided to
try the Ruby idiom of modifying an object on the fly and over-ride
it’s paintComponent(g) method as shown below [method display3]. I am
pretty sure I got the idiom right, so am I bumping up against a
limitation of JRuby or have I botched the invocation or is it a
bug…

module TinoGraphics
require ‘java’
import java.awt.image.BufferedImage
import javax.swing.JButton
import javax.swing.JFrame
class TGPanel < javax.swing.JPanel
def initialize(image)
@image=image
super()
end
def paintComponent(g)
g.drawImage(@image,0,0,@image.getWidth,@image.getHeight,self)
puts “paintComponent of TGPanel”
end
end

class Utility
def initialize
#for future use
end
def resize(original,xscale,yscale)
x=original.getWidth/xscale
y=original.getHeight/yscale
b2=original.getScaledInstance(x,y,BufferedImage::SCALE_SMOOTH)
bi2=BufferedImage.new(x,y,BufferedImage::TYPE_INT_RGB)
graphics = bi2.createGraphics
graphics.drawImage(b2,0,0,nil)
graphics.dispose
return bi2
end
def resize(original,x,y)
b2=original.getScaledInstance(x,y,BufferedImage::SCALE_SMOOTH)
bi2=BufferedImage.new(x,y,BufferedImage::TYPE_INT_RGB)
graphics = bi2.createGraphics
graphics.drawImage(b2,0,0,nil)
graphics.dispose
return bi2
end
def display(image) #plain old JButton/Icon hack
x=image.getWidth
y=image.getHeight
frame=JFrame.new(“Quick Display”)
frame.setSize(x,y)
panel=JButton.new(javax.swing.ImageIcon.new(image))
frame.setContentPane(panel)
frame.setVisible(true)
end
def display2(image) #using inheritance
x=image.getWidth
y=image.getHeight
frame=JFrame.new(“Quick Display 2”)
frame.setSize(x,y)
panel=TGPanel.new(image)

 frame.setContentPane(panel)
 frame.setVisible(true)

end
def display3(image) #using anonymous instance
x=image.getWidth
y=image.getHeight
frame=JFrame.new(“Quick Display 3”)
frame.setSize(x,y)
panel=javax.swing.JPanel.new
#let’s do an instance over-ride.
class << panel
def setImage(image)
@image=image
end
def getImage
@image
end
def paintComponent(g)
g.drawImage(@image,
0,0,@image.getWidth,@image.getHeight,self)
puts “paintComponent of panel instance”
end
end
panel.setImage(image)
frame.setContentPane(panel)
frame.setVisible(true)
frame.repaint
end
end
end

import javax.imageio.ImageIO
#debugger will need to insert their own jpg file below
img = ImageIO.read(java.io.File.new(“G:\wildpics
\crystal_face.jpg”));
u=TinoGraphics::Utility.new
u.display2(img) #works as expected!
u.display3(img) #does not work :frowning:

On Wed, Jun 10, 2009 at 12:20 PM, Curator1[email protected] wrote:

I like when learning a new language to play around with how to do
things. Â So in one case I did the two standard java idioms in JRuby to
display an image [methods dispaly and display2], and then decided to
try the Ruby idiom of modifying an object on the fly and over-ride
it’s paintComponent(g) method as shown below [method display3]. Â I am
pretty sure I got the idiom right, so am I bumping up against a
limitation of JRuby or have I botched the invocation or is it a
bug…

 def display3(image) #using anonymous instance
  x=image.getWidth
  y=image.getHeight
  frame=JFrame.new(“Quick Display 3”)
  frame.setSize(x,y)
  panel=javax.swing.JPanel.new
#let’s do an instance over-ride.
  class << panel

import javax.imageio.ImageIO
#debugger will need to insert their own jpg file below
img = ImageIO.read(java.io.File.new(“G:\wildpics
\crystal_face.jpg”));
u=TinoGraphics::Utility.new
u.display2(img) #works as expected!
u.display3(img) #does not work :frowning:

Yes, this is expected. In the display2 case you’re actually extending
a Java class, so you gain the ability to override whatever methods you
like. In the display3 case, the Java inheritance/dispatch semantics
are already set in stone, and we can’t force Java to dispatch to Ruby
from already-bound Java code. Your best options would be to just
create another subclass or create a single subclass for which you can
provide different logic on a per-object basis (like a version that
delegates to an object of your choice, and then you just provide it on
construct or set it into an attribute.

  • Charlie