【问题标题】:JavaFX Drag and drop to GridPane?JavaFX 拖放到 GridPane?
【发布时间】:2018-10-21 11:18:15
【问题描述】:

我已经在我的游戏中实现了拖放功能,但到目前为止我只能“拖放”到硬编码的位置。如图所示:

我想要的是:

  1. 当船只掉落时,它的 x,y 值(与 GridPane 相关)被保存,或者
  2. 飞船降落到的单元格被保存。

我的 setOnDragDropped 事件在这里处理:

//Drag dropped draws the image to the receiving node
    target.setOnDragDropped(new EventHandler<DragEvent>() {
        public void handle(DragEvent event) {
            //Data dropped
            //If there is an image on the dragboard, read it and use it
            Dragboard db = event.getDragboard();
            boolean success = false;
            int x, y;
            if(db.hasImage()){
                //target.setText(db.getImage()); --- must be changed to target.add(source, col, row)
                //target.add(source, 5, 5, 1, 1);
                //Places at 0,0 - will need to take coordinates once that is implemented
                Board.add(test, 0, 0, 1, 1);
                success = true;
            }
            //let the source know whether the image was successfully transferred and used
            event.setDropCompleted(success);

            event.consume();
        }
    });

我觉得这应该很容易作为 MouseOver 事件或类似的东西来做,但我不知道该怎么做。

编辑:以下类的完整代码:

public class Controller implements Initializable{
@FXML
public GridPane Board;
public GridPane ShipsToBePlaced;
public Rectangle MessageBox;
public Button ReadyButton;
public Button QuitButton;
public ImageView[][] water;
public ImageView[] ships;
public ImageView[][] ships2d;

@Override
public void initialize(URL location, ResourceBundle resources) {
    //Adds water to each cell in grid
    water = new ImageView[10][10];
    //ships2d = new ImageView[10][10];
    for(int i =0; i<10; i++){
        for(int j=0; j <10; j++){
            water[i][j] = new ImageView("Tiles/watertile.png");
            water[i][j].setPreserveRatio(true);
            water[i][j].setFitHeight(49);
            water[i][j].setFitWidth(49);
            Board.add(water[i][j], i, j);
            //ships2d[i][j] = new ImageView("Ships/ship2.png");
            //ships2d[i][j].setPreserveRatio(true);
            //ships2d[i][j].setFitWidth(49);
            //Board.add(ships2d[i][j], i, j);

        }
    }
    //Adds ships
    ships = new ImageView[5];
    ships[0] = new ImageView("Ships/ship2.png");
    ships[1] = new ImageView("Ships/ship3.png");
    ships[2] = new ImageView("Ships/ship3.png");
    ships[3] = new ImageView("Ships/ship4.png");
    ships[4] = new ImageView("Ships/ship5.png");
    for(int i=0; i < 5; i++){
        ships[i].setPreserveRatio(true);
    }
    ships[0].setFitWidth(80);
    ships[1].setFitWidth(120);
    ships[2].setFitWidth(120);
    ships[3].setFitWidth(160);
    ships[4].setFitWidth(200);
    //ShipsToBePlaced.add(ships[0], 0, 0);
    ShipsToBePlaced.add(ships[1], 0, 1);
    ShipsToBePlaced.add(ships[2], 0, 2);
    ShipsToBePlaced.add(ships[3], 0, 3);
    ShipsToBePlaced.add(ships[4], 0, 4);


    //Test imageview for dropped ship
    ImageView test = new ImageView("Ships/ship2.png");
    test.setPreserveRatio(true);
    test.setFitWidth(80);


    //First attempt at drag and drop
    ImageView source = new ImageView ("Ships/ship2.png");
    source.setPreserveRatio(true);
    source.setFitWidth(80);
    ShipsToBePlaced.add(source, 0, 0);
    final GridPane target = Board;

    //Drag detected event handler is used for adding drag functionality to the boat node
    source.setOnDragDetected(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent event) {
            //Drag was detected, start drap-and-drop gesture
            //Allow any transfer node
            Dragboard db = source.startDragAndDrop(TransferMode.ANY);

            //Put ImageView on dragboard
            ClipboardContent cbContent = new ClipboardContent();
            cbContent.putImage(source.getImage());
            //cbContent.put(DataFormat.)
            db.setContent(cbContent);
            source.setVisible(false);
            event.consume();
        }
    });

    //Drag over event handler is used for the receiving node to allow movement
    target.setOnDragOver(new EventHandler<DragEvent>() {
        public void handle(DragEvent event) {
            //data is dragged over to target
            //accept it only if it is not dragged from the same node
            //and if it has image data
            if(event.getGestureSource() != target && event.getDragboard().hasImage()){
                //allow for moving
                event.acceptTransferModes(TransferMode.MOVE);
            }
            event.consume();
        }
    });

    //Drag entered changes the appearance of the receiving node to indicate to the player that they can place there
    target.setOnDragEntered(new EventHandler<DragEvent>() {
        public void handle(DragEvent event) {
            //The drag-and-drop gesture entered the target
            //show the user that it is an actual gesture target
            if(event.getGestureSource() != target && event.getDragboard().hasImage()){
                source.setVisible(false);
                target.setOpacity(0.7);
                System.out.println("Drag entered");
            }
            event.consume();
        }
    });

    //Drag exited reverts the appearance of the receiving node when the mouse is outside of the node
    target.setOnDragExited(new EventHandler<DragEvent>() {
        public void handle(DragEvent event) {
            //mouse moved away, remove graphical cues
            source.setVisible(true);
            target.setOpacity(1);

            event.consume();
        }
    });

    //Drag dropped draws the image to the receiving node
    target.setOnDragDropped(new EventHandler<DragEvent>() {
        public void handle(DragEvent event) {
            //Data dropped
            //If there is an image on the dragboard, read it and use it
            Dragboard db = event.getDragboard();
            boolean success = false;
            int x, y;
            if(db.hasImage()){
                //target.setText(db.getImage()); --- must be changed to target.add(source, col, row)
                //target.add(source, 5, 5, 1, 1);
                //Places at 0,0 - will need to take coordinates once that is implemented
                Board.add(test, 0, 0, 1, 1);
                success = true;
            }
            //let the source know whether the image was successfully transferred and used
            event.setDropCompleted(success);

            event.consume();
        }
    });

    source.setOnDragDone(new EventHandler<DragEvent>() {
        public void handle(DragEvent event) {
            //the drag and drop gesture has ended
            //if the data was successfully moved, clear it
            if(event.getTransferMode() == TransferMode.MOVE){
                source.setVisible(false);
            }
            event.consume();
        }
    });
}

}

【问题讨论】:

  • targetGridPane 还是 GridPane 的子代?
  • 是的,抱歉,我不想包含整个文件,但目标是对名为 board 的 GridPane 的引用(因此是 Board.add 调用)

标签: java javafx javafx-8


【解决方案1】:

如果您可以访问实际删除它的Node,您可以确定GridPane 中的索引并为新节点使用相同的索引和/或以任何其他方式使用索引。 .

在这种情况下,您可以使用DragEvent.getPickResult().getIntersectedNode()Event.getTarget 获取目标ImageView

public void handle(DragEvent event) {
    //Data dropped
    //If there is an image on the dragboard, read it and use it
    Dragboard db = event.getDragboard();
    boolean success = false;
    Node node = event.getPickResult().getIntersectedNode();
    if(node != target && db.hasImage()){

        Integer cIndex = GridPane.getColumnIndex(node);
        Integer rIndex = GridPane.getRowIndex(node);
        int x = cIndex == null ? 0 : cIndex;
        int y = rIndex == null ? 0 : rIndex;
        //target.setText(db.getImage()); --- must be changed to target.add(source, col, row)
        //target.add(source, 5, 5, 1, 1);
        //Places at 0,0 - will need to take coordinates once that is implemented
        ImageView image = new ImageView(db.getImage());

        // TODO: set image size; use correct column/row span
        Board.add(image, x, y, 1, 1);
        success = true;
    }
    //let the source know whether the image was successfully transferred and used
    event.setDropCompleted(success);

    event.consume();
}

注意:由于您使用系统剪贴板使用拖动事件,其他应用程序可能是拖动手势的源或目标...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    相关资源
    最近更新 更多