How to drag and drop button onto GridPane?

人走茶凉 提交于 2020-11-30 00:37:47

问题


I'm working on a school project creating a simple battleship game and i want to use the Drag And Drop function to drag buttons from HBox on the bottom of the screen to the GridPane that the player uses to place ships on. But i can't get it to work properly. Here's a picture of my board per now.

I have tried to use the button.setOnMouseDragged(e -> {CODE HERE}); but it doesnt work.

Here is the code i used for my window

public class GridOrganizer {

    private BorderPane borderPane;

    public GridOrganizer() {
        borderPane = new BorderPane();
        borderPane.setStyle("-fx-background-color: grey;");
        borderPane.setPrefHeight(600);
        borderPane.setPrefWidth(600);
        createGrid();
    }

    public void createGrid() {
        //Creates the grids where the game is played and buttons/ships to place on grid

        GridPane playerGrid = new GridPane();
        GridPane enemyGrid = new GridPane();
        Insets padding = new Insets(10);

        //Create playergrid
        for (int i = 0; i < 10; i++) {
            playerGrid.getColumnConstraints().add(new ColumnConstraints(50)); //50 wide
            playerGrid.getRowConstraints().add(new RowConstraints(50)); 
        }
        //Create enemygrid
        for (int i = 0; i < 10; i++) {
            enemyGrid.getColumnConstraints().add(new ColumnConstraints(50)); //50 wide
            enemyGrid.getRowConstraints().add(new RowConstraints(50));
        }
        //looping through row and columns and adds buttons
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                Button button = new Button();
                button.setPrefHeight(50);
                button.setPrefWidth(50);
                GridPane.setConstraints(button, j, i); //(button, column, row)
                playerGrid.getChildren().add(button); //add button on each index

                button.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent arg0) {
                        //HIT or MISS
                        System.out.println("Row: " + GridPane.getRowIndex(button) + ", Column: " + GridPane.getColumnIndex(button)); 
                        button.setStyle("-fx-background-color: grey;");
                    }
                });
            }
        }
        //..same with enemy grid
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                Button button = new Button();
                button.setPrefHeight(50);
                button.setPrefWidth(50);
                GridPane.setConstraints(button, j, i); //(button, column, row)
                enemyGrid.getChildren().add(button); //add button on each index

                button.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent arg0) {
                        System.out.println("Row: " + GridPane.getRowIndex(button) + ", Column: " + GridPane.getColumnIndex(button)); 
                        button.setStyle("-fx-background-color: grey;");
                    }
                });
            }
        }

        //Make buttons for the ships
        Button rowboat = new Button("Rowboat");
        Button sailboat = new Button("Sailboat");
        Button submarine = new Button("Submarine");
        Button destroyer = new Button("Destroyer");
        Button battleship = new Button("Battleship");

        //Size the ship buttons to match game description
        battleship.setPrefHeight(50);
        battleship.setPrefWidth(250); //size 5
        destroyer.setPrefHeight(50);
        destroyer.setPrefWidth(200); //size 4
        submarine.setPrefHeight(50);
        submarine.setPrefWidth(150); //size 3
        sailboat.setPrefHeight(50);
        sailboat.setPrefWidth(150); //size 3
        rowboat.setPrefHeight(50);
        rowboat.setPrefWidth(100); //size 2

        //Drags button
        rowboat.setOnMouseDragged(e -> {
            //CODE HERE
        });

        //Drops button on grid
        //CODE HERE 


        sailboat.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) {
                //PLACE SHIP
            }
        });

        submarine.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) {
                //PLACE SHIP
            }
        }); 

        destroyer.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) {
                //PLACE SHIP
            }
        });

        battleship.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) {
                //PLACE SHIP
            }
        });

        HBox ships = new HBox(); //Horizontal box
        ships.getChildren().addAll(rowboat, sailboat, submarine, destroyer, battleship); //Add buttons to horizontal box

        //Add grids and ship buttons to pane with padding 
        borderPane.setLeft(enemyGrid); 
        BorderPane.setMargin(enemyGrid, padding);
        borderPane.setRight(playerGrid);
        BorderPane.setMargin(playerGrid, padding);
        borderPane.setBottom(ships);
        BorderPane.setMargin(ships, padding);
    }

    public Pane getGrid() {
        return borderPane;
    }
}


回答1:


The plan here is to start a drag event with the data needed to create your button when the drag event finished. In your code, it looks like you have added the Buttons into the Grid already. That means you need to only transfer a String to change the Button's text. In my code, I am using a StackPane when creating the Grid. I then create and add the Buttons later. You approach may be better. I have looked that far. I have added an MCVE (Altered code from here):

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/**
 * Demonstrates a drag-and-drop feature.
 */
public class HelloDragAndDrop extends Application
{

    @Override
    public void start(Stage stage)
    {
        //Source Buttons.
        final Button boat1 = new Button("boat1");
        final Button boat2 = new Button("boat2");
        final Button boat3 = new Button("boat3");
        final Button boat4 = new Button("boat4");

        //Adding OnDragDetected to source Buttons.
        setOnDragDetected(boat1);
        setOnDragDetected(boat2);
        setOnDragDetected(boat3);
        setOnDragDetected(boat4);

        //Adding onDragDone to source Buttons.
        setOnDragDone(boat1);
        setOnDragDone(boat2);
        setOnDragDone(boat3);
        setOnDragDone(boat4);

        //Creating GridPane
        GridPane gridPane = new GridPane();
        gridPane.setVgap(5);
        gridPane.setHgap(5);
        gridPane.setPadding(new Insets(5, 5, 5, 5));
        gridPane.setStyle("-fx-background-color: black;");
        //Adding StackPane to every Cell in the GridPane and Adding the Target Events to each StackPane.
        for (int i = 0; i < 6; i++) {
            StackPane stackPane = new StackPane();
            stackPane.setPrefSize(150, 50);
            stackPane.setStyle("-fx-background-color: yellow;");
            setOnDragOver(stackPane);
            setOnDragEntered(stackPane);
            setOnDragExited(stackPane);
            setOnDragDropped(stackPane);

            gridPane.add(stackPane, i / 3, i % 3);
        }

        HBox root = new HBox(new VBox(boat1, boat2, boat3, boat4), gridPane);
        stage.setTitle("Hello Drag And Drop");
        Scene scene = new Scene(root, 400, 200);
        stage.setScene(scene);
        stage.show();
    }

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

    //source events handlers
    public void setOnDragDetected(Button source)
    {
        source.setOnDragDetected((MouseEvent event) -> {
            /* drag was detected, start drag-and-drop gesture*/
            System.out.println("onDragDetected");

            /* allow any transfer mode */
            Dragboard db = source.startDragAndDrop(TransferMode.ANY);

            /* put a string on dragboard */
            ClipboardContent content = new ClipboardContent();
            content.putString(source.getText());
            db.setContent(content);

            event.consume();
        });
    }

    public void setOnDragDone(Button source)
    {
        source.setOnDragDone((DragEvent event) -> {
            /* the drag-and-drop gesture ended */
            System.out.println("onDragDone");
            /* if the data was successfully moved, clear it */
//            if (event.getTransferMode() == TransferMode.MOVE) {
//                source.setText("");
//            }

            event.consume();
        });
    }

    //target event handlers
    public void setOnDragOver(StackPane target)
    {
        target.setOnDragOver((DragEvent event) -> {
            /* data is dragged over the target */
            System.out.println("onDragOver");

            /* accept it only if it is  not dragged from the same node
            * and if it has a string data */
            if (event.getGestureSource() != target
                    && event.getDragboard().hasString()) {
                /* allow for both copying and moving, whatever user chooses */
                event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
            }

            event.consume();
        });
    }

    public void setOnDragEntered(StackPane target)
    {
        target.setOnDragEntered((DragEvent event) -> {
            /* the drag-and-drop gesture entered the target */
            System.out.println("onDragEntered");
            /* show to the user that it is an actual gesture target */
            if (event.getGestureSource() != target
                    && event.getDragboard().hasString()) {
                target.setStyle("-fx-background-color: green;");
            }

            event.consume();
        });
    }

    public void setOnDragExited(StackPane target)
    {
        target.setOnDragExited((DragEvent event) -> {
            /* mouse moved away, remove the graphical cues */
            target.setStyle("-fx-background-color: transparent;");

            event.consume();
        });
    }

    public void setOnDragDropped(StackPane target)
    {
        target.setOnDragDropped((DragEvent event) -> {
            /* data dropped */
            System.out.println("onDragDropped");
            /* if there is a string data on dragboard, read it and use it */
            Dragboard db = event.getDragboard();
            boolean success = false;
            if (db.hasString()) {
                //target.setText(db.getString());
                Button tempBoat = new Button(db.getString());
                tempBoat.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
                target.getChildren().clear();
                target.getChildren().add(tempBoat);
                success = true;
            }
            /* let the source know whether the string was successfully
            * transferred and used */
            event.setDropCompleted(success);

            event.consume();
        });
    }    
}

In this code, the Buttons that represent the Boats all have onDragDetected and onDragDone event handlers attached. They are considered Source/start of a Drag event. For every cell in the GridPane, a StackPane is added. These StackPanes are considered the Target/areas to drop drag events. Each StackPane has onDragOver, onDragEntered, onDragDropped, and onDragExited attached. Once a drag event is complete, the StackPane/Target that receives the event gets a new Button as a child with the same name as the Source Button.



来源:https://stackoverflow.com/questions/55709178/how-to-drag-and-drop-button-onto-gridpane

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!