2015-07-21 46 views
0

我在MazeUI類中有一些代碼,它在JavaFX中創建了幾個字段,用於輸入要生成的迷宮的高度和寬度以及按鈕和按鈕的事件。點擊生成迷宮時,代碼應該生成一個隨機迷宮。爲什麼gc.clearRect不能清除畫布?

現在,這工作正常。但是在迷宮最初使用gc.clearRect(x,y,z,a)繪製之後清除畫布的線條似乎不起作用,並且迷宮在隨後的點擊中重新繪製在另一個之上:

package dojo.maze.ui; 

import dojo.maze.generator.MazeGenerator; 
import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.geometry.Insets; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.TextField; 
import javafx.scene.effect.BoxBlur; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.VBox; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.StrokeLineCap; 
import javafx.scene.shape.StrokeLineJoin; 
import javafx.stage.Stage; 

public class MazeUI extends Application { 

private MazeGenerator generator; 
private Integer height = 15; 
private Integer width = 15; 

@Override 
public void start(Stage primaryStage) throws Exception { 
    primaryStage.setTitle("Dojo: Solving a Maze"); 

    Group root = new Group(); 

    drawMazeView(root); 

    primaryStage.setScene(new Scene(root, Color.WHITE)); 
    primaryStage.show(); 
} 


private GraphicsContext initialiseGraphicsContext(Canvas canvas) { 
    GraphicsContext gc = canvas.getGraphicsContext2D(); 
    gc.setFill(Color.BLACK); 
    gc.fillRect(0,0,600,600); 
    gc.setStroke(Color.GREEN); 
    gc.setLineCap(StrokeLineCap.ROUND); 
    gc.setLineJoin(StrokeLineJoin.ROUND); 
    gc.setLineWidth(3); 

    BoxBlur blur = new BoxBlur(); 
    blur.setWidth(1); 
    blur.setHeight(1); 
    blur.setIterations(1); 
    gc.setEffect(blur); 
    return gc; 
} 

private void drawMazeView(Group root) { 
    Canvas canvas = new Canvas(800, 800); 
    GraphicsContext gc = initialiseGraphicsContext(canvas); 

    GridPane.setConstraints(canvas, 0, 6); 

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

    Label heightLabel = new Label("Height:"); 
    final TextField heightTextField = new TextField(); 
    HBox hbHeight = new HBox(); 
    hbHeight.getChildren().addAll(heightLabel, heightTextField); 
    hbHeight.setSpacing(10); 

    GridPane.setConstraints(hbHeight, 0, 0); 

    Label widthLabel = new Label("Label:"); 
    final TextField widthTextField = new TextField(); 
    HBox hbWidth = new HBox(); 
    hbWidth.getChildren().addAll(widthLabel, widthTextField); 
    hbWidth.setSpacing(10); 

    GridPane.setConstraints(hbWidth, 0, 2); 

    VBox fieldsBox = new VBox(); 
    fieldsBox.getChildren().addAll(hbHeight, hbWidth); 

    // Create button that allows you to generate a new maze 
    Button btn = new Button(); 
    btn.setText("Generate Random Maze"); 
    btn.setOnAction(new EventHandler<ActionEvent>() { 

     @Override 
     public void handle(ActionEvent event) { 
      System.out.println("Button clicked!"); 
      height = Integer.valueOf(heightTextField.getText()); 
      width = Integer.valueOf(widthTextField.getText()); 

      // clear old maze 
      gc.clearRect(0, 0, 
        canvas.getHeight(), 
        canvas.getWidth()); 

      generator = new MazeGenerator(height, width); 

      drawMaze(gc); 
     } 
    }); 

    GridPane.setConstraints(btn, 0, 4); 

    grid.getChildren().addAll(fieldsBox, btn, canvas); 
    root.getChildren().add(grid); 
} 

void drawMaze(GraphicsContext gc) { 
    int[][] maze = generator.maze(); 
    int xPos = 20, 
     yPos = 20, 
     length = 40, 
     gap = 10; 

    for (int i = 0; i < width; i++) { 
     xPos = 20; 
     // draw the north edge 
     for (int j = 0; j < height; j++) { 
      if ((maze[j][i] & 1) == 0) { 
       gc.strokeLine(xPos, yPos, xPos + length, yPos); // horizontal 
      } 
      xPos += length + gap; 

      System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+ "); 
     } 
     System.out.println("+"); 

     xPos = 20; 
     // draw the west edge 
     for (int j = 0; j < height; j++) { 
      if ((maze[j][i] & 8) == 0) { 
       gc.strokeLine(xPos, yPos, xPos, yPos + length); // vertical 
      } 
      xPos += length + gap; 

      System.out.print((maze[j][i] & 8) == 0 ? "| " : " "); 
     } 
     gc.strokeLine(xPos, yPos, xPos, yPos + length); // vertical 
     System.out.println("|"); 
     yPos += length + gap; 
    } 
    // draw the bottom line 

    xPos = 20; // reset x pos to western edge 

    for (int j = 0; j < height; j++) { 
     gc.strokeLine(xPos, yPos, xPos + length, yPos); // horizontal 
     System.out.print("+---"); 
     xPos += length + gap; 
    } 
    System.out.println("+"); 
} 

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

代碼MazeGenerator:

package dojo.maze.generator; 

import java.util.Arrays; 
import java.util.Collections; 

/* 
* recursive backtracking algorithm 
* shamelessly borrowed from the ruby at 
* http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking 
*/ 
public class MazeGenerator { 

private final int x; 
private final int y; 
private final int[][] maze; 

public static final int[][] mazeProblemOne = new int[][] {{2,5,2,3,7,3,1,6,7,3,3,5,6,3,5},{4,10,3,5,12,6,3,9,10,3,5,12,8,6,13},{12,6,5,12,12,14,3,1,6,3,9,10,3,9,12},{12,12,12,12,12,12,6,3,9,4,6,7,1,6,9},{14,9,10,9,12,12,12,6,5,12,12,10,5,12,4},{12,2,7,5,12,12,10,9,12,10,13,4,10,9,12},{12,6,9,12,12,12,2,5,10,5,10,11,3,3,13},{12,10,5,12,10,11,3,13,4,10,5,6,3,1,12},{12,6,9,10,5,4,6,9,12,6,9,12,6,3,9},{10,9,6,1,12,10,11,3,9,12,6,13,12,2,5},{6,7,9,6,9,6,3,3,3,9,8,12,12,6,13},{8,12,6,9,6,13,6,3,7,3,3,13,12,12,12},{6,9,10,5,12,12,12,4,10,3,5,8,12,12,8},{14,3,5,12,8,12,10,11,3,5,10,5,12,10,5},{10,1,10,11,3,9,2,3,3,11,1,10,11,3,9}}; 
public static final int[][] mazeProblemTwo = new int[][] {{2,5,6,5,6,3,1,6,3,3,7,5,2,3,5},{4,10,9,12,14,3,3,9,6,5,12,10,3,3,9},{14,3,3,9,8,6,3,5,12,12,10,3,3,3,5},{12,6,3,3,5,12,4,10,9,10,3,3,3,3,13},{12,12,6,5,12,12,10,3,3,3,5,6,3,3,9},{12,10,9,12,10,9,6,5,6,3,13,10,3,3,5},{10,3,5,12,6,5,12,10,9,4,14,3,3,1,12},{4,6,9,12,12,10,9,6,3,11,13,6,3,3,9},{12,12,2,13,14,3,5,8,6,5,8,10,3,3,5},{12,10,3,9,12,4,12,6,9,12,6,5,6,3,9},{14,7,3,1,10,13,12,12,4,12,12,10,9,6,1},{12,10,3,7,1,12,10,11,9,12,12,2,3,11,5},{12,2,5,12,6,9,2,5,6,9,10,3,3,5,12},{10,5,12,12,12,6,3,13,12,6,7,1,6,9,12},{2,11,9,10,11,9,2,9,10,9,10,3,11,3,9}}; 
public static final int[][] mazeProblemThree = new int[][] {{2,5,2,3,7,3,3,3,5,6,3,1,6,7,1},{4,10,3,5,12,2,5,6,9,10,3,3,9,14,5},{10,7,5,12,10,5,14,9,6,5,6,3,5,12,12},{6,9,8,10,3,9,12,6,13,12,10,5,12,12,12},{12,6,3,7,1,6,9,12,12,10,3,9,12,8,12},{12,12,4,10,5,10,5,8,14,3,5,2,11,3,13},{12,10,13,4,10,5,10,5,10,5,10,5,6,5,12},{14,1,12,10,5,14,1,12,6,9,4,10,9,12,12},{14,5,10,5,12,10,5,12,12,2,15,3,1,12,12},{8,12,6,9,10,5,12,12,10,3,9,6,3,9,12},{6,9,14,3,3,9,12,10,3,3,3,9,4,6,9},{10,5,12,6,3,3,13,6,3,3,1,6,11,9,4},{6,9,12,10,5,6,11,9,6,3,3,9,6,3,13},{14,5,12,4,12,10,1,6,9,6,5,2,13,4,12},{8,10,11,9,10,3,3,11,3,9,10,3,9,10,9}}; 
public static final int[][] mazeProblemFour = new int[][] {{2,3,3,5,4,6,7,3,3,5,6,5,6,3,5},{6,3,1,12,12,12,10,3,5,10,9,12,10,5,12},{12,6,3,9,14,9,4,6,9,2,3,11,1,12,12},{14,9,2,3,11,5,12,10,3,5,6,3,3,9,12},{10,5,6,5,2,11,11,5,4,12,12,6,7,1,12},{4,10,9,10,3,5,6,9,12,10,9,8,12,6,13},{14,5,4,6,3,9,12,6,11,5,6,3,9,12,8},{12,10,9,12,4,6,9,10,5,12,14,3,5,10,5},{12,6,5,12,12,12,6,3,9,12,8,6,13,4,12},{14,9,10,9,12,12,10,3,5,10,5,12,10,13,12},{12,2,7,5,10,11,3,3,9,6,9,12,2,9,12},{10,3,9,10,3,3,5,4,6,11,3,9,6,3,13},{6,5,6,7,3,5,12,10,9,6,3,3,9,6,9},{12,10,9,10,5,8,12,6,5,10,5,6,5,10,5},{10,3,3,1,10,3,11,9,10,3,9,8,10,3,9}}; 
public static final int[][] mazeProblemFive = new int[][] {{2,3,5,6,3,3,7,5,6,3,3,3,7,3,5},{6,5,12,12,6,3,9,8,10,5,4,6,9,4,12},{12,12,12,12,10,3,5,6,5,10,13,10,5,14,9},{12,10,9,10,5,4,10,9,14,1,12,4,12,10,5},{10,5,6,5,10,15,3,1,14,5,14,9,10,5,8},{6,9,12,10,5,8,6,5,8,10,9,6,5,14,5},{10,3,9,4,12,6,9,10,3,3,3,9,12,8,12},{6,3,7,13,12,10,7,5,2,7,7,1,10,3,13},{14,1,12,8,10,5,12,12,6,9,12,6,3,3,9},{8,6,13,6,3,9,12,12,12,2,13,12,6,3,5},{6,9,8,12,4,6,9,12,14,5,8,10,9,4,12},{12,6,3,9,10,9,6,9,8,10,7,5,6,11,9},{12,10,3,3,3,5,14,3,3,5,12,12,10,5,4},{14,1,6,5,6,9,10,3,1,12,12,10,1,10,13},{10,3,9,10,11,3,3,3,3,9,10,3,3,3,9}}; 

public MazeGenerator(int x, int y) { 
    this.x = x; 
    this.y = y; 
    maze = new int[this.x][this.y]; 
    generateMaze(0, 0); 
} 

public void display() { 
    for (int i = 0; i < y; i++) { 
     // draw the bbc.north edge 
     for (int j = 0; j < x; j++) { 
      System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+ "); 
     } 
     System.out.println("+"); 
     // draw the west edge 
     for (int j = 0; j < x; j++) { 
      System.out.print((maze[j][i] & 8) == 0 ? "| " : " "); 
     } 
     System.out.println("|"); 
    } 
    // draw the bottom line 
    for (int j = 0; j < x; j++) { 
     System.out.print("+---"); 
    } 
    System.out.println("+"); 
} 

private void generateMaze(int cx, int cy) { 
    DIR[] dirs = DIR.values(); 
    Collections.shuffle(Arrays.asList(dirs)); 
    for (DIR dir : dirs) { 
     int nx = cx + dir.dx; 
     int ny = cy + dir.dy; 
     if (between(nx, x) && between(ny, y) 
       && (maze[nx][ny] == 0)) { 
      maze[cx][cy] |= dir.bit; 
      maze[nx][ny] |= dir.opposite.bit; 
      generateMaze(nx, ny); 
     } 
    } 
} 

private static boolean between(int v, int upper) { 
    return (v >= 0) && (v < upper); 
} 

public int[][] maze() { 
    return maze; 
} 

private enum DIR { 
    N(1, 0, -1), S(2, 0, 1), E(4, 1, 0), W(8, -1, 0); 
    private final int bit; 
    private final int dx; 
    private final int dy; 
    private DIR opposite; 

    // use the static initializer to resolve forward references 
    static { 
     N.opposite = S; 
     S.opposite = N; 
     E.opposite = W; 
     W.opposite = E; 
    } 

    private DIR(int bit, int dx, int dy) { 
     this.bit = bit; 
     this.dx = dx; 
     this.dy = dy; 
    } 
}; 

public static void main(String[] args) { 
    int x = args.length >= 1 ? (Integer.parseInt(args[0])) : 8; 
    int y = args.length == 2 ? (Integer.parseInt(args[1])) : 8; 
    MazeGenerator maze = new MazeGenerator(x, y); 
    maze.display(); 
} 
} 

如何修復代碼以便正確每個按鈕後清除迷宮點擊?我錯過了什麼嗎?

+2

請不要爲這樣的問題發佈太多的代碼。相反,請創建一個[最小示例](http://stackoverflow.com/help/mcve),可以複製和粘貼來運行和複製,但僅提供複製問題所需的代碼量。 – jewelsea

+0

沒有粘貼該代碼,你怎麼知道你可以複製這個問題?這是一個用戶界面,所以我需要繪製完整的畫布。唯一額外的是領域。但那不是那麼多額外的代碼。你需要生成畫布代碼來渲染完整的迷宮。這是顯示工作問題的最小示例 –

+0

我可能會刪除導入語句(因爲它們是隱含的),但即使如此,查看使用哪個庫以防萬一出現問題也很有幫助 –

回答

1

在清除畫布之前刪除BoxBlur效果,然後重新應用它。清除畫布只需使用透明顏色進行塗抹。所以BoxBlur效果也會影響到這一點。

什麼jewelsea說。如果你只是將代碼降到最低,你本可以自己找到的;-)

+0

感謝Roland - 認爲我會堅持它如果有人知道答案,然後才能弄清楚。我是JavaFX的新手,所以還不習慣這種怪癖。 如果這解決了我的問題,我會報告回來 - 謝謝。 –

+0

非常感謝你! 我解決了它通過使用removeBoxBlur(gc)之前的gc.clearRect和一個setBoxBlur(gc)之後的按鈕操作。 removeBoxBlur(gc)基本上是gc.setEffect(null); 接受此解決方案。 –