如何在JavaFX中刷新面板

3

我最近在学习JavaFX,有一个关于如何刷新面板的问题。在这个简单的程序中,我希望黑色正方形在我点击移动按钮时向右移动到下一个块中,但它没有起作用,我想知道如何修复我的代码。

截图

主类:

public class Main extends Application {
    private Cell cells[] = new Cell[5];
    private Player player;
    private Board board;
    Button move = new Button("move");

    public Main() throws Exception {
        for (int i = 0; i < cells.length; i++) {
            cells[i] = new Cell(i);
        }
        this.player = new Player(0, cells);
        this.board = new Board(player, cells);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Main game = new Main();
        BorderPane pane = new BorderPane();
        pane.setCenter(board);
        pane.setBottom(move);

        Scene scene = new Scene(pane,400,80);
        primaryStage.setTitle("Move");
        primaryStage.setScene(scene); 
        primaryStage.show();

        move.setOnAction(e -> game.move());
    }
    public void move() {
        player.currentCell.index += 1;
        board.paint();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

板(Board)类:

class Board extends Pane {
    private Player player;
    public Cell cells[];
    private final int CELLWIDTH = 40;
    private final int CELLHEIGHT = 40;
    private final int LMARGIN = 100;

    public Board(Player p, Cell cells[]) {
        player = p;
        this.cells = cells;
        paint();
    }

    public void paint() {
        Cell cell;
        for (int i=0; i<cells.length; i++) {
            cell = cells[i];
            Rectangle r1 = new Rectangle(xCor(cell.index), 0, CELLWIDTH, CELLHEIGHT); 
            r1.setStroke(Color.BLACK); 
            r1.setFill(Color.WHITE);
            getChildren().add(r1);
        }

        cell = player.currentCell;
        Rectangle r2 = new Rectangle(xCor(cell.index), 0, CELLWIDTH, CELLHEIGHT); 
        r2.setFill(Color.BLACK);
        getChildren().add(r2);
    }
    private int xCor(int col) {
        return LMARGIN + col * CELLWIDTH;
    }
}

玩家类:

class Player {
    public int position;
    public Cell currentCell;
    public Player(int position, Cell cell[]) throws Exception {
        this.currentCell = cell[0];
    }
}

单元格类:

class Cell {
    public int index;
    public Cell(int index) {
        this.index = index;
    }
}

你有检查我发布的代码吗?那解决了你的问题吗? - Draken
1
为什么要创建第二个 Main 实例?应该是 move.setOnAction(e -> this.move());。此外,您正在不断向 Board 添加更多的 Rectangle,但从未将它们删除。这是有意为之吗? - fabian
更新了答案并在我的设备上使其正常工作,希望能有所帮助。 - Draken
1个回答

2
你可能需要修改你的代码,只将玩家位置存储在Player类中会使生活变得困难。我建议在Cell类中添加一个标志,表示玩家是否在里面。例如:
class Cell {
    public int index;
    private Player playerInCell;
    public Cell(int index) {
        this.index = index;
    }
    public void setPlayerInCell(Player p){
        this.playerInCell = p;
    }
    public void clearPlayerInCell(){
        this.playerInCell = null;
    }
    public Player getPlayerInCell(){
        return this.playerInCell;
    }
}

然后,当将玩家移动到“Cell”时,您可以将其从先前的“Cell”中清除并设置为新“Cell”的内容,在您的“Paint()”函数中,如果存在玩家,请着色该单元格。 另一件事,如果您希望保持自己的方法,那么问题是因为您仅更改了“Cell”类的“index”属性,您还应该更改“cells []”数组中的“Cell”位置或只更改“Player”类的“currentCell”属性,否则您的玩家始终停留在同一位置。以下是更改“Player”的“currentCell”属性的示例:
public void move() {
    Cell currentCell = player.currentCell;
    Cell nextCell = null;
    for (int i = 0; i < cells.length; i++) {
        if (cells[i] == currentCell && i+1 < cells.length){
            nextCell = cells[i+1];
            break;
        }
    }
    if (nextCell != null)
        player.currentCell = nextCell;
    else{
        //Error handling, next cell not found
    }
    board.paint();
}

[编辑]

我做了一些重要的代码清理,你之前的某些写法有点奇怪,希望你不介意,以下是已更改的类:

Main(主类)

public class Main extends Application {

    private Cell cells[] = new Cell[5];
    private Player player;
    private Board board;
    Button move = new Button("move");

    public Main() throws Exception{
        for (int i = 0; i < cells.length; i++) {
            cells[i] = new Cell(i);
        }
        this.player = new Player(cells[0]);
        this.board = new Board(player, cells);
    }

    @Override
    public void start(Stage primaryStage) throws Exception{
        BorderPane pane = new BorderPane();
        pane.setCenter(board);
        pane.setBottom(move);

        Scene scene = new Scene(pane,400,80);
        primaryStage.setTitle("Move");
        primaryStage.setScene(scene);
        primaryStage.show();

        move.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                move();
            }
        });
    }

    public void move() {
        //Get current players cell, we want to move them one right
        Cell currentCell = player.getCurrentCell();
        Cell nextCell = null;
        //Searching for current cell in board, if found we need to clear the player from it and select the next cell
        for (int i = 0; i < cells.length; i++) {
            if (cells[i] == currentCell && i+1 < cells.length){
                cells[i].clearPlayerInCell();
                nextCell = cells[i+1];
                break;
            }
        }
        //We found it, let's move the player
        if (nextCell != null) {
            player.setCurrentCell(nextCell);
            nextCell.setPlayerInCell(player);
        }
        //We didn't find it, or our index was out of range, what do we do now?
        else{
            //Error handling, next cell not found
            //Example, let's put them back at the start
            player.setCurrentCell(cells[0]);
            cells[0].setPlayerInCell(player);
            cells[cells.length-1].clearPlayerInCell();
        }
        board.paint();
    }


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

板块

public class Board extends Pane {
    private Player player;
    private Cell cells[];
    private final int CELLWIDTH = 40;
    private final int CELLHEIGHT = 40;
    private final int LMARGIN = 100;

    public Board(Player p, Cell cells[]) {
        player = p;
        this.cells = cells;
        paint();
    }

    public Cell[] getCells(){
        return this.cells;
    }

    public Player getPlayer() {
        return player;
    }

    public void paint() {
        //Clear previous cells, we don't need them now
        getChildren().clear();
        //Redraw them
        for(Cell cell : cells){
            Rectangle r1 = new Rectangle(xCor(cell.getIndex()), 0, CELLWIDTH, CELLHEIGHT);
            r1.setStroke(Color.BLACK);
            //We've found a player in the cell, let's colour it black
            if (cell.getPlayerInCell() != null)
                r1.setFill(Color.BLACK);
            //No, player in this cell, white it is
            else
                r1.setFill(Color.WHITE);
            getChildren().add(r1);
        }
    }
    private int xCor(int col) {
        return LMARGIN + col * CELLWIDTH;
    }
}

播放器

public class Player {
    private Cell currentCell;
    public Player(Cell cell) throws Exception {
        this.currentCell = cell;
        cell.setPlayerInCell(this);
    }
    public Cell getCurrentCell(){
        return this.currentCell;
    }

    public void setCurrentCell(Cell cell){
        this.currentCell = cell;
    }
}

单元格

public class Cell {
    private int index;
    private Player playerInCell;
    public Cell(int index) {
        this.index = index;
    }
    public void setPlayerInCell(Player p){
        this.playerInCell = p;
    }
    public void clearPlayerInCell(){
        this.playerInCell = null;
    }
    public Player getPlayerInCell(){
        return this.playerInCell;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
}

现在代码能运行了,我可以将单元格移动,如果玩家到达末尾,我还设置了单元格返回到开头的功能,这只是一个示例。
它的原理是使用 playerInCellCell 属性,如果该属性不为空,则我们知道有玩家在该单元格中,并且可以将其涂黑。如果它为空,就没有玩家在单元格中,我们可以将其涂白。这也允许你在未来可能拥有更多不同颜色的玩家。但我不知道你的最终目标是什么。希望这可以帮助你,如果你需要进一步的解释,请随时问。
此外,要了解更多信息,请参见这里,了解为什么使用像我一样的getter和setter更好。
另外,这段代码的理由:
move.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent actionEvent) {
        move();
    }
});

由于我使用的是Java 1.7而不是Java 1.8,因此无法使用谓词,您可以安全地将其更改为move.setOnAction(e -> this.move());


点击按钮后,玩家的currentCell已更改,但黑色方块仍未移动。仍然无法正常工作。 - Chen
啊,我看到另外一个问题了,等一下。 - Draken

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接