Во-первых, вы устанавливаете момент времени для всех ваших ключевых кадров на одно и то же значение (одну секунду), чтобы они все происходили одновременно. Вам нужно, чтобы каждый ключевой кадр имел разные временные точки, поэтому они происходят последовательно.
Во-вторых, вы сортируете массив, а затем обработчики событий для ключевых кадров ссылаются на массив. Поскольку обработчики событий для ключевых кадров выполняются позже, они видят только отсортированный массив. Вы должны фактически манипулировать массивом в обработчиках событий для ключевых кадров.
В-третьих, вы играете на временной шкале несколько раз. Вам нужно играть в нее только один раз. Кроме того, вы устанавливаете счетчик циклов на INDEFINITE
: я думаю, что вам нужно анимировать сортировку только один раз. (Если вы действительно хотите, чтобы оно повторялось, вам нужно вернуть массив в исходный порядок в начале временной шкалы.)
Наконец, у вас есть некоторые проблемы в реализации фактического алгоритма сортировки. Вот почему ваше приложение зависает при случайном заполнении массива. Я не буду решать эти проблемы здесь, потому что вопрос в том, как выполнить анимацию.
Следующий код выполняет пошаговую анимацию. Вероятно, это не правильно реализованная сортировка, поэтому вы не увидите ожидаемой анимации, но она по крайней мере перерисовывает эффект перестановок в анимации:
import java.util.Random;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.util.Duration;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class AnimatedSort extends Application
{
final int SCALE = 16;
final int WIDTH = 64;
final int HEIGHT = 32;
int[][] pixels;
Timeline sortLoop;
int[] myArray = {32,28,22,20,16,13,10,9,5,3};
@Override
public void start(Stage primaryStage) throws Exception
{
pixels = new int[WIDTH][HEIGHT];
// int[] myArray = new int[WIDTH];
//
//
// Random rand = new Random();
// for (int i = 0; i < WIDTH; i++)
// {
// myArray[i] = rand.nextInt((HEIGHT) + 1);
// }
Canvas display = new Canvas (WIDTH*SCALE, HEIGHT*SCALE);
GraphicsContext gc = display.getGraphicsContext2D();
GridPane grid = new GridPane();
grid.add(display, 0, 0);
primaryStage.setTitle("Sort");
primaryStage.setScene(new Scene(grid, WIDTH*SCALE, HEIGHT*SCALE));
primaryStage.show();
sortLoop = new Timeline();
// sortLoop.setCycleCount(Timeline.INDEFINITE);
// Sort array
for (int index = 0; index < myArray.length - 1; index++)
{
final int i = index ;
KeyFrame kf = new KeyFrame(Duration.seconds(i+1), actionEvent -> {
if (myArray[i] > myArray[i + 1])
{
int swap = myArray[i];
myArray[i] = myArray[i + 1];
myArray[i + 1] = swap;
// i = -1;
}
// Clear screen by zeroing out pixel array
for (int k = 0; k < WIDTH; k++)
{
for (int j = 0; j < HEIGHT; j++)
{
pixels[k][j] = 0;
}
}
// Draw array with vertical bars (assign values to canvas array)
for (int k = 0; k < myArray.length; k++)
{
for (int j = (HEIGHT - 1); j > ((HEIGHT - myArray[k]) - 1); j--)
{
pixels[k][j] = 1;
}
}
// Render canvas
for (int k = 0; k < WIDTH; k++)
{
for (int j = 0; j < HEIGHT; j++)
{
if (pixels[k][j] == 1)
{
gc.setFill(Color.WHITE);
gc.fillRect((k*SCALE), (j*SCALE), SCALE, SCALE);
}
else
{
gc.setFill(Color.BLACK);
gc.fillRect((k*SCALE), (j*SCALE), SCALE, SCALE);
}
}
}
});
sortLoop.getKeyFrames().add(kf);
}
sortLoop.play();
}
public static void main(String[] args)
{
launch(args);
}
}