2015-04-02 66 views
-2

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

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

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

该问题位于扩展TimerClass的内部ScheduleTask类中。在运行时(使用Java),ScheduleTask的run()方法允许调用它所属的Board对象的repaint()方法。这在Java中非常方便:在正常的时间间隔内,Board面板重新绘制。如何在JRuby中翻译此内容?我只是试图字面翻译这一点,但随后的重绘方法不是由红宝石内部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类已提取从董事会...

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 \t 
 
    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

最后这里是启动应用程序的方式:

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

+0

究竟是用代码您的问题,我不明白你的问题。 – phoet 2015-04-02 21:11:24

+0

@phoet。我稍微修改了我对问题的解释和我在Ruby中的尝试。与Java相比,在Ruby中使用内部类,我们失去了repaint()方法的可见性。 – JCLL 2015-04-03 07:59:30

+0

与'jruby swing.rb'正常工作 - 没有错误打印/发生在运行时! – kares 2015-04-05 17:45:04

回答

0

我终于成功地解决我的概率lem,使用这个blog

  1. 创建一个定时器
  2. 添加一个方法“add_action_listener(块)”
  3. 传意动作块
1

你覆盖paintComponent但从未调用继承的版本(这实际上做的工作) - 这可能是一个问题。 ..调用它在Ruby版本的正确方法是一个简单的super语句(或更加明确super(g)):

def paintComponent(g) 
    super # super(g) 
    drawStar(g) 
end 
+0

这有效地解决了翻译paintComponent方法的问题。但是,我最初关于内部类的问题仍然存在,这就是为什么我不勾选“解决”图标的原因。 – JCLL 2015-04-06 20:59:16