0

I am working on a game as a personal project. It involves tiles that appear both in a rack and on a game board. The rack is a GridPane and the board is a GridPane. I need to be able to drag and drop tiles both within the rack and board, as well as from one to the other.

I have reduced this to a single standalone class with two GridPane's. Each GridPane has one row and 10 columns. Each GridPane initially displays five "tiles". I need to be able to drag and drop any one of the tiles into any available position of either GridPane (i.e. any position that does not already have a tile).

TIA and Happy 4th!

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class DragAndDropDemoTool extends Application {
    public final double FONT_SIZE = 40;
    public final double NUMBER_OF_COLUMNS_PER_GRID = 10;
    public final double TILE_CURVATURE = 15;
    public final double TILE_SIZE = 50;
    public final double TEXT_POSITION_X = 13;
    public final double TEXT_POSITION_Y = 39;

    @Override
    public void start(Stage stage) throws Exception {
        final VBox rootPane = new VBox();

        rootPane.setPadding(new Insets(20));

        final GridPane topGridPane = new GridPane();
        final GridPane bottomGridPane = new GridPane();

        topGridPane.setHgap(5);
        bottomGridPane.setHgap(5);
        topGridPane.setVgap(10);
        bottomGridPane.setVgap(10);

        // Set equal column widths
        for (int i = 0; i < NUMBER_OF_COLUMNS_PER_GRID; i++) {
            ColumnConstraints columnConstraints = new ColumnConstraints();
            columnConstraints.setPercentWidth(100 / NUMBER_OF_COLUMNS_PER_GRID);
            topGridPane.getColumnConstraints().add(columnConstraints);
            bottomGridPane.getColumnConstraints().add(columnConstraints);
        }

        // Set fixed row height
        RowConstraints rowConstraints = new RowConstraints();
        rowConstraints.setMinHeight(TILE_SIZE + 6);
        topGridPane.getRowConstraints().add(rowConstraints);
        bottomGridPane.getRowConstraints().add(rowConstraints);

        final Canvas canvas0 = createNewTile("0");
        final Canvas canvas1 = createNewTile("1");
        final Canvas canvas2 = createNewTile("2");
        final Canvas canvas3 = createNewTile("3");
        final Canvas canvas4 = createNewTile("4");
        final Canvas canvas5 = createNewTile("5");
        final Canvas canvas6 = createNewTile("6");
        final Canvas canvas7 = createNewTile("7");
        final Canvas canvas8 = createNewTile("8");
        final Canvas canvas9 = createNewTile("9");

        topGridPane.add(canvas1, 1, 0);
        topGridPane.add(canvas3, 3, 0);
        topGridPane.add(canvas5, 5, 0);
        topGridPane.add(canvas7, 7, 0);
        topGridPane.add(canvas9, 9, 0);

        bottomGridPane.add(canvas0, 0, 0);
        bottomGridPane.add(canvas2, 2, 0);
        bottomGridPane.add(canvas4, 4, 0);
        bottomGridPane.add(canvas6, 6, 0);
        bottomGridPane.add(canvas8, 8, 0);

        VBox.setMargin(bottomGridPane, new Insets(20, 0, 0, 0));

        rootPane.getChildren().addAll(topGridPane, bottomGridPane);

        Scene scene = new Scene(rootPane);

        stage.setTitle(this.getClass().getSimpleName());
        stage.setScene(scene);
        stage.show();
    }

    public Canvas createNewTile(final String text) {
        final Canvas canvas = new Canvas(TILE_SIZE, TILE_SIZE);

        final GraphicsContext gc = canvas.getGraphicsContext2D();
        gc.setFill(Color.VIOLET);
        gc.fillRoundRect(0, 0, TILE_SIZE, TILE_SIZE, TILE_CURVATURE, TILE_CURVATURE);
        gc.setFill(Color.PURPLE);

        gc.setFont(Font.font("Arial", FONT_SIZE));
        gc.fillText(text, TEXT_POSITION_X, TEXT_POSITION_Y);

        return canvas;
    }

    public static void main(String[] args) {
        launch(args);
    }
}
chasse
  • 225
  • 2
  • 9
  • The basic strategy is to fill the grid pane to which you are dropping items with empty panes of come kind (e.g. `StackPane`). That way you have a target for the "drop". Off-topic: It's probably better to use a `Label` than a `Canvas` here, just style it appropriately to get the look you want. – James_D Jul 05 '23 at 15:30
  • See [this example](https://stackoverflow.com/a/71962336/1155209) for dragging nodes around a grid pane. Dragging between grid panes is no different. Dragging to empty spaces rather than filled ones would use the approach James outlined, only allowing the drop operation if the target node is an empty placeholder. – jewelsea Jul 06 '23 at 06:25

0 Answers0