将Java内部类转换为JRuby对应类

时间:2015-04-02 15:31:38

标签: jruby

我正在尝试将Java类转换为其JRuby计数器部分,但我不知道如何翻译Java 内部类。

这个问题众所周知,常常来自Java和Ruby之间的可见性/范围差异。这有时可以使用集团而不是内部类来解决。

Java示例如下,可以在Zetcode站点上找到。我也在下面给出了我的Ruby尝试。

该问题位于内部ScheduleTask类中,该类扩展了TimerClass。在运行时(在Java中),ScheduleTask的run()方法允许调用它所属的Board对象的repaint()方法。这在Java中非常方便:在常规时间间隔,Board面板重新绘制。如何在JRuby中翻译这个?我只是试图按字面翻译,但Ruby内部的ScheduleTask不知道重绘方法......



package com.zetcode;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JPanel;


public class Board extends JPanel  {

    private final int B_WIDTH = 350;
    private final int B_HEIGHT = 350;
    private final int INITIAL_X = -40;
    private final int INITIAL_Y = -40;    
    private final int INITIAL_DELAY = 100;
    private final int PERIOD_INTERVAL = 25;
    
    private Image star;
    private Timer timer;
    private int x, y;
    
    public Board() {
    
        
        initBoard();        
    }
    
    private void loadImage() {
        
        ImageIcon ii = new ImageIcon("star.png");
        star = ii.getImage();        
    }
    
    private void initBoard() {
        
        setBackground(Color.BLACK);
        setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
        setDoubleBuffered(true);
        
        loadImage();

        x = INITIAL_X;
        y = INITIAL_Y;
        
        timer = new Timer();
        timer.scheduleAtFixedRate(new ScheduleTask(), 
                INITIAL_DELAY, PERIOD_INTERVAL);        
    }
        

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        drawStar(g);
    }
    
    private void drawStar(Graphics g) {
        
        g.drawImage(star, x, y, this);
        Toolkit.getDefaultToolkit().sync();
    }


    private class ScheduleTask extends TimerTask {

        @Override
        public void run() {
            x += 1;
            y += 1;

            if (y > B_HEIGHT) {
                y = INITIAL_Y;
                x = INITIAL_X;
            }
            
            repaint();
        }
    }




这是JRuby尝试,其中ScheduleTask类已从Board ...

中提取出来



include Java

import java.awt.Color
import java.awt.Dimension
import java.awt.Graphics
import java.awt.Image
import java.awt.Toolkit
import java.util.Timer
import java.util.TimerTask
import javax.swing.ImageIcon
import javax.swing.JPanel

B_WIDTH = 650
B_HEIGHT = 450
INITIAL_X = -40
INITIAL_Y = -40    
INITIAL_DELAY = 100
PERIOD_INTERVAL = 25

class Board < JPanel

  def initialize
    super
    initBoard()        
  end
    
  def loadImage
    ii = ImageIcon.new("mario2.png")
    @star = ii.getImage()        
  end
    
  def initBoard
    setBackground(Color.new(255, 255, 255))
    setPreferredSize(Dimension.new(B_WIDTH, B_HEIGHT))
    setDoubleBuffered(true)
    loadImage()
    @x = INITIAL_X
    @y = INITIAL_Y
        
    @timer = Timer.new()
    task=ScheduleTask.new
    task.init(@x,@y)
    @timer.scheduleAtFixedRate(task, INITIAL_DELAY, PERIOD_INTERVAL)        
  end

  def paintComponent(g)
    repaint() # WAS : super.paintComponent(g)
    drawStar(g)
  end
    
  def drawStar(g)
    g.drawImage(@star, @x, @y, self)
    Toolkit.getDefaultToolkit().sync()
  end

  class ScheduleTask < TimerTask	
    def init x,y
      @x,@y=x,y
    end
    def run
      @x += 1
      @y += 1
      if (@y > B_HEIGHT) 
        @y = INITIAL_Y
        @x = INITIAL_X
       end
      repaint() # <===== ERROR in Ruby. Unknown method 
    end
  end #ScheduleTask 

 end #Board
&#13;
&#13;
&#13;

最后,这是启动应用程序的方法:

&#13;
&#13;
require_relative 'board'

include Java

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.SwingUtilities

class UtilityTimerExample < JFrame

    def initialize
      super
      initUI();
      setVisible(true)
    end
    
    def initUI
      add(Board.new());
      setResizable(false);
      pack();
      setTitle("Star");
      setLocationRelativeTo(nil)
      setDefaultCloseOperation(JFrame::EXIT_ON_CLOSE)
    end
end

SwingUtilities.invoke_later do
  UtilityTimerExample.new
end
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

你重写paintComponent但从不调用继承的版本(实际上是这样做的) - 这可能是一个问题...在Ruby版本中调用它的正确方法只是一个{ {1}}语句(或更明确的super):

super(g)

答案 1 :(得分:0)

我终于成功解决了我的问题,使用了blog

  1. 创建一个计时器
  2. 添加方法&#34; add_action_listener(block)&#34;
  3. 将预期的操作传递给块