我正在一个学校项目上创建一个简单的战舰游戏,我想使用拖放功能将按钮从屏幕底部的HBox拖动到玩家用来放置船只的GridPane。但是我无法使其正常工作。现在是picture of my board。
我尝试使用button.setOnMouseDragged(e-> {CODE HERE});但这不起作用。
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;
}
}
答案 0 :(得分:0)
此处的计划是在拖动事件结束时使用创建按钮所需的数据来启动拖动事件。在您的代码中,看起来您已经将Buttons
添加到了Grid
中。这意味着您只需要传送String
即可更改Button's
文本。在我的代码中,创建StackPane
时使用的是Grid
。然后,我稍后创建并添加Buttons
。您的方法可能更好。我已经看了那么远。我添加了MCVE(来自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();
});
}
}
在此代码中,代表Buttons
的{{1}}都附加了Boats
和onDragDetected
事件处理程序。它们被视为onDragDone
/拖动事件的开始。对于Source
中的每个单元格,将添加一个GridPane
。这些StackPane
被认为是StackPanes
/拖放事件区域。每个Target
都附加了StackPane
,onDragOver
,onDragEntered
和onDragDropped
。拖动事件完成后,接收事件的onDragExited
/ StackPane
会以与Target
Button
同名的孩子身份获得新的Source