如何减慢 java 中的程序执行速度?
How to slow down a program execution in java?
我创建了一个 JavaFX 程序来递归地绘制 Sierpinski 地毯,但我想查看递归函数的运行情况,即减慢程序的速度以实时查看它的绘制。为此,我尝试了这样的事情:
public void pause(int sleepTime)
{
try
{
Thread.sleep(sleepTime);
}
catch(InterruptedException e)
{
System.err.println("Error in running rotation animation!");
System.exit(-1);
}
}
然后我在我的 drawSierpinskiCarpet 函数中调用了这个函数,如下所示:
public void drawSeripinskiCarpet(GraphicsContext gc, int x, int y, int width, int height)
{
if(width != height || width < 3)
return;
int size = width /= 3;
gc.setFill(colors[index]);
gc.fillRect(x + size, y + size, size, size);
index++;
if(index == colors.length)
{
index = 0;
}
pause(1);
for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
if(i == 1 && j == 1)
{
continue;
}
drawSeripinskiCarpet(gc, x + j * size, y + i * size, size, size);
}
}
}
但是程序挂了几秒钟,然后直接出现了地毯。我看不到正在执行的程序。
对 GUI 的任何修改只会在修改后产生视觉结果 returns。同时,JavaFX 无法处理任何事件并冻结,直到您的操作完成。
您可以使用 Timeline
一次执行一个操作:使用堆栈数据执行一次绘图;这允许您一次执行一个绘图操作,此外还可以为 Timeline
.
的每一帧修改堆栈
@Override
public void start(Stage primaryStage) throws IOException {
Canvas canvas = new Canvas(729, 729);
final GraphicsContext gc = canvas.getGraphicsContext2D();
Scene the_scene = new Scene(new StackPane(canvas));
primaryStage.setScene(the_scene);
primaryStage.show();
final Color[] colors = new Color[] { Color.BLUE, Color.ORANGE, Color.GREEN, Color.RED, Color.BROWN,
Color.MAGENTA, Color.YELLOW, Color.CYAN, Color.BLACK };
class IndexHolder {
int index = 0;
Color getNextFill() {
Color fill = colors[index];
++index;
if (index >= colors.length) {
index = 0;
}
return fill;
}
}
final IndexHolder indexHolder = new IndexHolder();
class StackEntry {
int x;
int y;
int size;
public StackEntry(int x, int y, int size) {
this.x = x;
this.y = y;
this.size = size;
}
void executeStep(List<StackEntry> stack, IndexHolder indexHolder, GraphicsContext gc) {
int size = this.size /= 3;
gc.setFill(indexHolder.getNextFill());
gc.fillRect(x + size, y + size, size, size);
if (size >= 3) {
// add new "calls" in reverse order here
// (first call in original needs to be popped from the stack first)
for (int i = 2; i >= 0; --i) {
for (int j = 2; j >= 0; --j) {
if (i == 1 && j == 1) {
continue;
}
stack.add(new StackEntry(x + j * size, y + i * size, size));
}
}
}
}
}
// finally create the animation
final List<StackEntry> stack = new ArrayList<>();
stack.add(new StackEntry(0, 0, (int) canvas.getHeight()));
final Timeline timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(1),
evt -> {
// pop
StackEntry entry = stack.remove(stack.size() - 1);
entry.executeStep(stack, indexHolder, gc);
if (stack.isEmpty()) {
timeline.stop();
}
}));
timeline.play();
}
我创建了一个 JavaFX 程序来递归地绘制 Sierpinski 地毯,但我想查看递归函数的运行情况,即减慢程序的速度以实时查看它的绘制。为此,我尝试了这样的事情:
public void pause(int sleepTime)
{
try
{
Thread.sleep(sleepTime);
}
catch(InterruptedException e)
{
System.err.println("Error in running rotation animation!");
System.exit(-1);
}
}
然后我在我的 drawSierpinskiCarpet 函数中调用了这个函数,如下所示:
public void drawSeripinskiCarpet(GraphicsContext gc, int x, int y, int width, int height)
{
if(width != height || width < 3)
return;
int size = width /= 3;
gc.setFill(colors[index]);
gc.fillRect(x + size, y + size, size, size);
index++;
if(index == colors.length)
{
index = 0;
}
pause(1);
for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
if(i == 1 && j == 1)
{
continue;
}
drawSeripinskiCarpet(gc, x + j * size, y + i * size, size, size);
}
}
}
但是程序挂了几秒钟,然后直接出现了地毯。我看不到正在执行的程序。
对 GUI 的任何修改只会在修改后产生视觉结果 returns。同时,JavaFX 无法处理任何事件并冻结,直到您的操作完成。
您可以使用 Timeline
一次执行一个操作:使用堆栈数据执行一次绘图;这允许您一次执行一个绘图操作,此外还可以为 Timeline
.
@Override
public void start(Stage primaryStage) throws IOException {
Canvas canvas = new Canvas(729, 729);
final GraphicsContext gc = canvas.getGraphicsContext2D();
Scene the_scene = new Scene(new StackPane(canvas));
primaryStage.setScene(the_scene);
primaryStage.show();
final Color[] colors = new Color[] { Color.BLUE, Color.ORANGE, Color.GREEN, Color.RED, Color.BROWN,
Color.MAGENTA, Color.YELLOW, Color.CYAN, Color.BLACK };
class IndexHolder {
int index = 0;
Color getNextFill() {
Color fill = colors[index];
++index;
if (index >= colors.length) {
index = 0;
}
return fill;
}
}
final IndexHolder indexHolder = new IndexHolder();
class StackEntry {
int x;
int y;
int size;
public StackEntry(int x, int y, int size) {
this.x = x;
this.y = y;
this.size = size;
}
void executeStep(List<StackEntry> stack, IndexHolder indexHolder, GraphicsContext gc) {
int size = this.size /= 3;
gc.setFill(indexHolder.getNextFill());
gc.fillRect(x + size, y + size, size, size);
if (size >= 3) {
// add new "calls" in reverse order here
// (first call in original needs to be popped from the stack first)
for (int i = 2; i >= 0; --i) {
for (int j = 2; j >= 0; --j) {
if (i == 1 && j == 1) {
continue;
}
stack.add(new StackEntry(x + j * size, y + i * size, size));
}
}
}
}
}
// finally create the animation
final List<StackEntry> stack = new ArrayList<>();
stack.add(new StackEntry(0, 0, (int) canvas.getHeight()));
final Timeline timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(1),
evt -> {
// pop
StackEntry entry = stack.remove(stack.size() - 1);
entry.executeStep(stack, indexHolder, gc);
if (stack.isEmpty()) {
timeline.stop();
}
}));
timeline.play();
}