簡體   English   中英

如何在JavaFX(逐像素)畫布中創建填充動畫?

[英]How to create filling animation in JavaFX(pixel by pixel) canvas?

我正在為我的數字圖像拓撲學學校項目而苦苦掙扎。 我們的目標是編寫一個具有矩形的應用程序,該應用程序具有一條穿過該矩形的線,並且該應用程序需要填充該線下方的字段。 它需要使用某種類型的像素鄰域來逐像素填充它。

我設法編寫了一些應用程序,該應用程序填充了該行下方的字段,但它很快就填充了所有內容。 我無法逐個像素地完成它。 我嘗試停止線程,但無法停止應用程序線程,無法從應用程序以外的線程更新UI。 Platform.runLater或Task也不起作用。 我希望畫布在每次添加新像素時刷新,因此我有此動畫演示此算法的工作原理。

我希望我的解釋就足夠了。 您不必專注於我的項目,只是有人可以向我解釋如何在畫布中逐像素填充此像素嗎?

這是控制器的代碼:

@FXML
private Canvas canvas;

@FXML
private ComboBox<String> optionsType;

@FXML
private Button drawBtn;

@FXML
private ComboBox<String> optionsNeighbourhood;

WritableImage wi;
PixelReader pr;
GraphicsContext gc;

(...)

public void drawLine() {
    gc.strokeLine(0, 0, canvas.getWidth(), canvas.getHeight());
}

private void fillShape(Neighbourhood type, int startX, int startY) {

    int width = (int) canvas.getWidth();
    int height = (int) canvas.getHeight();

    LinkedList<Point> list = new LinkedList<>();
    list.addFirst(new Point(startX, startY));
    while (!list.isEmpty()) {
        Point point = list.removeLast();
        int x = point.getX();
        int y = point.getY();

        if (x >= 0 && x < width && y >= 0 && y < height && isEmpty(x, y)) {
            gc.fillRect(x, y, 1, 1);
            gc.fill();
            canvas.snapshot(null, wi);

            list.addFirst(new Point(x + 1, y));
            list.addFirst(new Point(x, y + 1));
            list.addFirst(new Point(x, y - 1));
            list.addFirst(new Point(x - 1, y));
            if (type == Neighbourhood.SIX || type == Neighbourhood.EIGHT) {
                if (isEmpty(x - 1, y) || isEmpty(x, y - 1)) {
                    list.add(new Point(x - 1, y - 1));
                }

                if (isEmpty(x + 1, y) || isEmpty(x, y + 1)) {
                    list.add(new Point(x + 1, y + 1));
                }
            }

            if (type == Neighbourhood.EIGHT) {
                if (isEmpty(x - 1, y) || isEmpty(x, y + 1)) {
                    list.add(new Point(x - 1, y + 1));
                }

                if (isEmpty(x + 1, y) || isEmpty(x, y + 1)) {
                    list.add(new Point(x + 1, y - 1));
                }
            }
        }

    }
}

private boolean isEmpty(int x, int y) {

    if (x < 0 || x >= canvas.getWidth() || y < 0 || y >= canvas.getHeight()) {
        return false;
    }

    if (!pr.getColor(x, y).toString().equals("0xffffffff")) {
        return false;
    }

    return true;
}

}

現在我知道代碼乍一看似乎不太明顯。 該算法無關緊要,因為它似乎確實起作用,但是主要問題是:如何使該字段逐個像素填充(就像動畫一樣(是的,我也嘗試過AnimationTimer)。

有幾種方法,一種方法是使用像這樣的AnimationTimer:

import java.util.Random;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class Main extends Application {

    private static double SCENE_WIDTH = 800;
    private static double SCENE_HEIGHT = 600;

    static Random random = new Random();

    Canvas canvas;
    GraphicsContext graphicsContext;

    AnimationTimer loop;

    Scene scene;

    @Override
    public void start(Stage primaryStage) {

        BorderPane root = new BorderPane();

        canvas = new Canvas(SCENE_WIDTH, SCENE_HEIGHT);

        graphicsContext = canvas.getGraphicsContext2D();

        Pane layerPane = new Pane();

        layerPane.getChildren().addAll(canvas);

        root.setCenter(layerPane);

        scene = new Scene(root, SCENE_WIDTH, SCENE_HEIGHT);

        primaryStage.setScene(scene);
        primaryStage.show();

        startAnimation();

    }

    private void startAnimation() {

        loop = new AnimationTimer() {

            double startX = 100;
            double endX = 200;
            double y = 100;
            double x = startX;
            double speed = 0.2;

            @Override
            public void handle(long now) {

                graphicsContext.fillOval(x, y, 5,5);

                x+=speed;

                if( x >= endX) {
                    loop.stop();
                }
            }
        };

        loop.start();

    }

    public static void main(String[] args) {
        launch(args);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM