将 Java 内部 class 翻译成 JRuby 对应物
Translating a Java internal class into a JRuby counterpart
我正在尝试将 Java class 翻译成它的 JRuby 对应部分,但我不知道如何翻译 Java 内部 class.
这个问题是众所周知的,通常来自 visibility/scope Java 和 Ruby 之间的差异。这有时可以使用 blocs 而不是 inner class.
来解决
Java 示例如下,可以在 Zetcode 网站上找到。我也在下面给出了我的 Ruby 尝试。
问题出在扩展 TimerClass 的内部 ScheduleTask class 中。而运行ning(在Java中),ScheduleTask的运行()方法允许调用其所属的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 class 已从 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
最后是启动应用程序的方法:
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
你重写了 paintComponent
但永远不会调用继承的版本(它实际上完成了工作) - 这可能是一个问题......在 Ruby 版本中调用它的正确方法只是一个 super
语句(或更明确的 super(g)
):
def paintComponent(g)
super # super(g)
drawStar(g)
end
我终于成功解决了我的问题,使用这个blog。
- 创建一个计时器
- 添加方法"add_action_listener(block)"
- 将预期的操作传递给块
我正在尝试将 Java class 翻译成它的 JRuby 对应部分,但我不知道如何翻译 Java 内部 class.
这个问题是众所周知的,通常来自 visibility/scope Java 和 Ruby 之间的差异。这有时可以使用 blocs 而不是 inner class.
来解决Java 示例如下,可以在 Zetcode 网站上找到。我也在下面给出了我的 Ruby 尝试。
问题出在扩展 TimerClass 的内部 ScheduleTask class 中。而运行ning(在Java中),ScheduleTask的运行()方法允许调用其所属的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 class 已从 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
最后是启动应用程序的方法:
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
你重写了 paintComponent
但永远不会调用继承的版本(它实际上完成了工作) - 这可能是一个问题......在 Ruby 版本中调用它的正确方法只是一个 super
语句(或更明确的 super(g)
):
def paintComponent(g)
super # super(g)
drawStar(g)
end
我终于成功解决了我的问题,使用这个blog。
- 创建一个计时器
- 添加方法"add_action_listener(block)"
- 将预期的操作传递给块