import javafx.application.Application; import javafx.application.Platform; import javafx.concurrent.Task; import javafx.geometry.Pos; import javafx.scene.layout.VBox; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.control.Button; import javafx.scene.paint.Color; import javafx.stage.Stage; public class BubbleSort2 extends Application { private final Color[] cs = {Color.RED, Color.BLUE}; private int[] init = {10, 52, 23, 34, 8, 12, 4, 46, 7, 45, 44, 3}; private int[] args = new int[init.length]; private final int scale = 10; private volatile Thread thread; private int i, j; private volatile boolean threadSuspended = true; private Canvas canvas; @Override public void start(Stage stage) throws Exception { stage.setTitle("バブルソート"); Button step = new Button("step"); step.setOnAction(e -> stepThread()); canvas = new Canvas(320,250); GraphicsContext gc = canvas.getGraphicsContext2D(); paint(gc); VBox root = new VBox(); root.setAlignment(Pos.CENTER); root.getChildren().addAll(step, canvas); stage.setScene(new Scene(root)); stage.show(); startThread(); } private synchronized void stepThread() { threadSuspended = false; notify(); } private void bubbleSort() { while (true) { for (int k = 0; k < init.length; k++) { args[k] = init[k]; } // バブルソートアルゴリズム for (i = 0; i < args.length - 1; i++) { for (j = args.length - 1; j > i; j--) { if (args[j - 1] > args[j]) { // スワップする。 int tmp = args[j - 1]; args[j - 1] = args[j]; args[j] = tmp; } Platform.runLater(() -> paint(canvas.getGraphicsContext2D())); /* repaint の後で止まる */ try { synchronized(this) { while (threadSuspended) { wait(); } threadSuspended = true; } } catch (InterruptedException e) {} } } } } private void startThread() { if (thread == null) { Task task = new Task() { @Override protected Void call() throws Exception { bubbleSort(); // 外側クラスのメソッドにしないと this があわない return null; } }; thread = new Thread(task); thread.setDaemon(true); thread.start(); } } private void paint(GraphicsContext gc) { gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); gc.setFill(Color.YELLOW); gc.fillOval(5, 30 + j * scale, scale, scale); gc.setFill(Color.CYAN); gc.fillOval(5, 30 + i * scale, scale, scale); int n = args.length; for (int i = 0; i < n; i++) { gc.setFill(cs[args[i] % 2]); gc.fillRect(20, 30 + i * scale, args[i] * scale / 2, scale); } } public static void main(String... args) { launch(args); } }