如何在Java FX上可视化矩阵

时间:2019-03-26 20:50:59

标签: java javafx data-visualization visualization

我有一个由0和1组成的矩阵。我想像网格一样可视化此矩阵,并在其中有1的单元格上标记。我进行了研究,以便找到在Java FX中执行此操作的方法,但找不到与我说的内容类似的内容。在Java FX中有什么方法可以做到这一点?最好的问候,

1 个答案:

答案 0 :(得分:1)

我在Java FX中使用GridPane和Timeline可视化了矩阵。由于上面c0der的评论,我找到了这种方法。在我的情况下,我需要在矩阵上绘制一条路径,就像找到最小路径问题一样。这是我的源代码:

    public class VisualizationThread implements EventHandler<ActionEvent> {

    private ArrayList<ArrayList<Integer>> matrix; // Matrix
    private ArrayList<Integer> solution; // One individual
    private ArrayList<ArrayList<Integer>> visited; // Visited coordinate list
    private int currentX; // Current x coordinate
    private int currentY; // Current y coordinate
    private int index; // Current movement index
    private int attempt; // unsuccessful attempt count (used while visualizing all generations)
    private boolean closeAtTheAnd; // Close all stages except the last one which shows final situation, the correct path
    private boolean isSuccessful; // Currently visualizing an unsuccessful attempt or correct path?
    private Stage primaryStage; // primary stage (gui component)

    public VisualizationThread(ArrayList<ArrayList<Integer>> matrix, ArrayList<Integer> solution, int currentX, int currentY,
                               boolean isSuccessful, int attempt, boolean closeAtTheAnd){
        this.matrix   = matrix;
        this.solution = solution;
        this.currentY = currentY;
        this.currentX = currentX;
        this.isSuccessful = isSuccessful;
        this.attempt = attempt;
        this.primaryStage = new Stage();
        this.index = 0;
        this.closeAtTheAnd = closeAtTheAnd;
        this.visited = new ArrayList<ArrayList<Integer>>();
    }

    // Visualize a single individual
    public void run() {

        // GUI processes
        BorderPane root = new BorderPane();

        GridPane grid = new GridPane();
        grid.setPadding(new Insets(10));
        grid.setHgap(10);
        grid.setVgap(10);

        StackPane[][] screen_buttons = new StackPane[matrix.size()][matrix.size()];

        visited.add(new ArrayList<Integer>(){{add(currentX); add(currentY);}});
        for (int y=0;y<matrix.size();y++) {
            for (int x=0;x<matrix.get(y).size();x++) {
                screen_buttons[y][x] = new StackPane();
                Rectangle rec = new Rectangle(60,60);
                // Visualize visited points as green and others yellow and foods red
                if(!(currentX>=matrix.size() || currentY>=matrix.size())){
                    if(isVisited(visited, x, y)){
                        rec.setFill(Color.GREEN);
                    }else {
                        rec.setFill(matrix.get(y).get(x) == 0 ? Color.YELLOW : Color.RED);
                    }
                }else {
                    rec.setFill(matrix.get(y).get(x) == 0 ? Color.YELLOW : Color.RED);
                }

                rec.setStyle("-fx-arc-height: 20; -fx-arc-width: 20;");
                screen_buttons[y][x].getChildren().addAll(rec);
                grid.add(screen_buttons[y][x], x, y);
            }
        }

        //container for controls
        GridPane controls = new GridPane();

        root.setCenter(grid);
        root.setBottom(controls);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.setTitle(isSuccessful ? "Correct Path" : "Unsuccessful Attempt: " + attempt);
        primaryStage.show();

        if(!(index >= solution.size())){
            switch (solution.get(index)){
                case 1:
                    setCurrentY(getCurrentY()-1);
                    break;
                case 2:
                    setCurrentX(getCurrentX()-1);
                    break;
                case 3:
                    setCurrentY(getCurrentY()+1);
                    break;
                case 4:
                    setCurrentX(getCurrentX()+1);
                    break;
            }

            index++;
        }

        if(closeAtTheAnd && index == solution.size()){
            primaryStage.close();
        }

    }

    // This method finds if current coordinate is visited before or not
    // @param visitedList: List of visited points
    // @param x: x coordinate
    // @param y: y coordinate
    public boolean isVisited(ArrayList<ArrayList<Integer>> visitedList, int x, int y){
        boolean result = false;

        // Check if x and y coordinates are visited before
        for (ArrayList<Integer> temp : visitedList){
            if(temp.get(0) == x && temp.get(1) == y){
                result = true;
                break;
            }
        }

        return result;
    }

    public int getCurrentX() {
        return currentX;
    }

    public void setCurrentX(int currentX) {
        this.currentX = currentX;
    }

    public int getCurrentY() {
        return currentY;
    }

    public void setCurrentY(int currentY) {
        this.currentY = currentY;
    }

    public void handle(ActionEvent event) {
        run();
    }
}

// In another part of the code which I need to trigger the event above.
ArrayList<Integer> bestOfLastPopulation = geneticAlgorithm.findMostAte(finalPopulation, matrix, centerX, centerY);
VisualizationThread visualizationThread = new VisualizationThread(matrix, bestOfLastPopulation, centerX, centerY, true, 0, false);

Timeline fiveSecondsWonder = new Timeline(new KeyFrame(Duration.millis(150), visualizationThread));

fiveSecondsWonder.setCycleCount(bestOfLastPopulation.size() + 1);
fiveSecondsWonder.play();

对于试图找到相同事物的人,应查看以嵌套的for循环开始并以primaryStage.show()结尾的部分。在代码的这一部分,它以不同的颜色可视化矩阵。例如,如果一个单元格包含1,则为红色,如果一个单元格包含0,则为黄色,如果之前访问过该单元格,则将其涂成绿色。希望对别人有帮助。最好的问候,