【问题标题】:Swapping nodes in a Gridpane for chess game在国际象棋游戏的 Gridpane 中交换节点
【发布时间】:2019-12-05 19:48:36
【问题描述】:

我无法单击一个按钮,然后单击另一个按钮与之前单击的按钮交换。然后将第一个点击的按钮设为空白按钮。

我想不出该怎么做。我只是尝试使用 if 语句,例如

If button = this{                 //this should find the first button
    if button = that{             //this should find the second button
       that = this                //this swaps the buttons
    }
   this = blank                  //and ends with making the first button 
blank
}

这不起作用,因为它直接通过了第二个 if 语句,并使第一个按钮空白而不交换任何内容。

不需要太多代码,这只是测试代码来找出这个单一的动作

public class SimpleButtonSwapper extends Application {

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

    @Override
    public void start(Stage stage) {

        GridPane pane = new GridPane();
        pane.setPadding(new Insets(50, 50, 50, 50));           //creates 50 pixel padding
        pane.setVgap(2);
        pane.setHgap(2);

        Scene scene = new Scene(pane);

        Canvas canvas = new Canvas(50, 400);
        GraphicsContext graphics = canvas.getGraphicsContext2D();
        pane.getChildren().add(canvas);

        stage.setTitle("Chess");

        Button[] buttons = new Button[6];

        for (int i = 0; i < 6; i++) {
            buttons[i] = new Button();
            buttons[i].setText("banana " + i);
        }

        for (int i = 0; i < 6; i++) {
            pane.add(buttons[i], i, 0);
        }

        for (int i = 0; i < 6; i++) {

            buttons[i].setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {

                }
            });
        }

        stage.setScene(scene);

        stage.show();
    }
}

【问题讨论】:

  • 这个GridPane应该只按住按钮吗? Canvas 的目的是什么?
  • 我不确定 GridPane 还能保存什么,除非您的意思是让另一个类将自己包裹在按钮数组上?我不知道画布的用途,我对 javafx 很陌生,这就是我的书解释构建图形显示的方式

标签: java javafx gridpane


【解决方案1】:

以下是mreGridPane 中交换两个按钮:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class FxMain extends Application {

    private static final int COLS = 5, ROWS = 5;
    private int clickCounter = 0;
    private GridPane grid;
    private Button first, second;

    @Override
    public void start(Stage primaryStage){

        VBox root = new VBox(10);
        root.setPadding(new Insets(10));
        root.getChildren().addAll(makeGrid(), new Text("Click 2 buttons to swap them"));
        primaryStage.setScene(new Scene(root));
        primaryStage.sizeToScene();
        primaryStage.show();
    }

    private Pane makeGrid() {

        grid = new GridPane();
        for(int rowIndex = 0; rowIndex < ROWS ; rowIndex++) {
            //an array to hold buttons of one row 
            Node[] nodes = new Node[COLS];
            for(int colIndex = 0; colIndex < COLS ; colIndex++) {
                Button node= new Button(rowIndex+""+colIndex);
                node.setOnAction(e->buttonCliked(e.getSource())); //add action listener 
                node.prefHeight(100); node.prefWidth(100);
                nodes[colIndex]= node;
            }
            grid.addRow(rowIndex, nodes);
        }
        return grid;
    }

    private void buttonCliked(Object source) {

        if(!(source instanceof Button)) return;
        Button button  = (Button)source;

        if(clickCounter == 0){
            first = button;
        }else{
            second = button;
            swap();
        }

        System.out.println(clickCounter + " " + ((Button)source).getText()    );
        clickCounter=  ++clickCounter %2 ;  // changes values between 0 1
    }

    private void swap() {
        int firstRow = GridPane.getRowIndex(first);
        int firstCol = GridPane.getColumnIndex(first);
        int secondRow = GridPane.getRowIndex(second);
        int secondCol = GridPane.getColumnIndex(second);
        grid.getChildren().removeAll(first, second);
        grid.add(first, secondCol, secondRow);
        grid.add(second, firstCol, firstRow);
    }

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

【讨论】:

  • 该死,只是为了交换几个按钮?我有一些工作要尝试理解这段代码。我非常感谢这篇文章
  • 那么您不需要使用事件处理程序来使用按钮吗?这是我被教导的唯一方法。
  • 节点数组的作用是什么?我看到nodes[colIndex]= node; 将按钮对象分配给它,但为什么呢?我从未使用过节点类,oracle 文档解释说它是场景图节点的基类。在这种情况下,所有图形形式的事物都是节点吗?是否有类似类型的类做同样的事情,或者这是应该始终用于按钮和其他图形的类?
  • 查看我添加的 cmets。每个按钮都分配有一个偶数处理程序。 Node 类是Control 类的超类。请参阅here 完整的层次结构。如果您觉得它令人困惑,您可以使用Button[]
【解决方案2】:

您可以创建一个属性来保存选定的按钮状态....但我认为“更改文本”并不能真正帮助您创建国际象棋游戏。我会有一个“ChessPiece”对象及其基础规则/属性...

 SimpleObjectProperty<Button> selectedButtonProperty = new SimpleObjectProperty<>();

 for (int i = 0; i < 6; i++)
 {

     buttons[i].setOnAction(new EventHandler<ActionEvent>()
     {
         @Override
         public void handle(ActionEvent event)
         {
             Button thisButton = (Button) event.getSource();
             if (selectedButtonProperty.get() == null)
             {
                selectedButtonProperty.set(thisButton);
             } else
             {
                 thisButton.setText(selectedButtonProperty.get().getText());
                 selectedButtonProperty.get().setText(null);
                 selectedButtonProperty.set(null);
             }

         }
     });

  }

【讨论】:

  • 是的,这只是用于计算交换动作的代码,我的其他代码包含棋子的所有类以及与按钮数组无关的类。好的,所以您的建议与另一条消息相似,只是您使用的代码看起来好像您知道自己在做什么哈哈
  • 这类似于我将按钮保持在原位并仅更改其外观。另一个建议采用实际按钮并移动它们。您必须决定哪种方法最好。他/她使用了一个 for-each 循环,这很好,但在这种情况下,当您真正使用网格时,您的循环样式实际上更清晰 imo。
【解决方案3】:

我真的不知道这在国际象棋游戏中有何用处,但这是我在 gridPane 中交换两个按钮所做的操作

我为第一次单击的按钮创建了一个变量,该变量在您单击按钮之前将保持为“null”,因此第一次单击会将单击的按钮保存在“第一次”中,第二次单击将交换并删除内容'第一'

要交换它们,我必须检索它们在 gridPane 中的位置(我只保存了列索引,您可能还需要保存行索引)

//looping through the buttons
for (Button button : buttons) {
    //adding a listener
    button.setOnAction(e -> {
        if (first == null)
            first = button;
        else {
            if (first != button) {
                Button second = button;
                int index1 = GridPane.getColumnIndex(first);
                int index2 = GridPane.getColumnIndex(second);
                pane.getChildren().removeAll(first, second);
                pane.add(first, index2, 0);
                pane.add(second, index1, 0);
            }
            first = null;
        }
    });
}

【讨论】:

  • 语句“for(Button button :buttons)”有什么作用?对于 else if 部分,在什么情况下单击按钮不会提示变量首先被发现为 null 并被分配按钮,它不会被发现为 != 按钮?如果这有任何意义吗?只是为了安慰吗?
  • for(Button button:buttons) 是一个for-each循环(你可以查一下),注意你仍然可以使用你的方法循环遍历数组,变量first不会为null如果您以前单击过一个按钮,如果您单击一个按钮并且 first 为空,则该按钮将首先保存,因此下次单击按钮时,first 不会为空,因此程序知道这是您单击的第二个按钮和知道是时候交换了,关于第二个 if 语句,它只检查你是否试图交换同一个按钮,所以它不会进行交换,如果你点击同一个按钮两次什么都没有发生
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
  • 2016-04-04
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多