JRubyでFilthyRichClients


半年ほど前にFilthyRichClientsを読んだけど、いろいろ忘れているので復習する。
せっかくなので、JRubyでサンプルコードを書きなおしながら勉強してみる。
まずは、chapter2の楕円とハイライト表示のコードを書いてみよう。

楕円を描く

require 'java'

include_class 'java.awt.Color'
include_class %w( JFrame JComponent SwingUtilities).map{|s| 'javax.swing.' + s}

class OvalComponent < JComponent
  def paintComponent(g)
    g.setColor(getBackground())
    g.fillRect(0, 0, getWidth(), getHeight())
    g.setColor(Color::RED)
    g.fillOval(0, 0, getWidth(), getHeight())
  end
end

SwingUtilities.invokeLater do
  f = JFrame.new
  f.setTitle("OvalComponent")
  f.add(OvalComponent.new)
  f.setDefaultCloseOperation(JFrame::EXIT_ON_CLOSE);
  f.setSize(200, 200);
  f.setVisible(true);
end

実行結果

JComponentを継承したクラスをつくって、paintComponentをオーバーライドした。
setColorで赤色に設定して、fillOvalで円を描いている。赤い楕円が表示される。

ハイライト表示

JButtonのテキストにハイライトを付ける。

require 'java'

include_class %w( AlphaComposite Color FlowLayout RadialGradientPaint ).map{|s| 'java.awt.' + s}
include_class %w( JFrame JButton SwingUtilities ).map{|s| 'javax.swing.' + s}
include_class 'java.awt.image.BufferedImage'
include_class 'java.awt.geom.Point2D'

class HighlightButton < JButton
  HIGHLIGHT_SIZE = 18
  
  def initialize(text)
    super(text)
    @highlight_image = create_highlight_image()
  end
  
  def create_highlight_image
    img = BufferedImage.new(HIGHLIGHT_SIZE, HIGHLIGHT_SIZE, BufferedImage::TYPE_INT_ARGB)
    g = img.createGraphics()
    
    # 背景
    g.setComposite(AlphaComposite::Clear)
    g.fillRect(0, 0, HIGHLIGHT_SIZE, HIGHLIGHT_SIZE)
    
    # グラデーションを作成
    g.setComposite(AlphaComposite::SrcOver)
    center = Point2D::Float.new(HIGHLIGHT_SIZE/2, HIGHLIGHT_SIZE/2)
    radius = HIGHLIGHT_SIZE/2.0
    dist = [0.0, 0.85].to_java(:float)
    colors = [Color.white, Color.new(255, 255, 255, 0)].to_java('java.awt.Color'.to_sym)
    paint = RadialGradientPaint.new(center, radius, dist, colors)
    
    g.setPaint(paint)
    g.fillOval(0, 0, HIGHLIGHT_SIZE, HIGHLIGHT_SIZE);
    g.dispose()
    img
  end
  
  def paintComponent(g)
    super(g)
    g.drawImage(@highlight_image, getWidth()/4, getHeight()/4, nil)
  end
end

SwingUtilities.invokeLater do
  f = JFrame.new
  f.setTitle("OvalComponent")
  f.getContentPane().setLayout(FlowLayout.new);
  f.add(JButton.new("standard"))
  f.add(HighlightButton.new("highlight"))
  f.setDefaultCloseOperation(JFrame::EXIT_ON_CLOSE);
  f.setSize(100, 100)
  f.setVisible(true);
end

実行結果

JButtonを継承するクラスでpaintComponentをオーバーライドした。
create_highlight_imageの中がごちゃごちゃしてるけど、BufferedImageをつくって、そこにグラデーションを書いています。
paintComponentの中では、まずデフォルトの描画を行い(superの呼び出し)、
そのあとcreate_highlight_imageで作ったImageを描画しています。下のJButtonのほうに、微妙にハイライトが付いている。

RadialGradientPaintをつくるのに、色々とto_javaするのが大変。。。もっと上手な方法あるのかな。