我正在尝试将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;
最后,这是启动应用程序的方法:
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;
答案 0 :(得分:1)
你重写paintComponent
但从不调用继承的版本(实际上是这样做的) - 这可能是一个问题...在Ruby版本中调用它的正确方法只是一个{ {1}}语句(或更明确的super
):
super(g)
答案 1 :(得分:0)
我终于成功解决了我的问题,使用了blog。