简体   繁体   中英

JavaFX - Drag and Drop TableCell

I've got a TableView with cells in it. My Table works like a Coordinate System, not like a usual Table. Click here for more about this.

Now, i need to Drag and Drop one Cell to another (Move).

Here is my Code for Drag and Drop:

tableView.setOnDragDetected(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            Dragboard db = tableView.startDragAndDrop(TransferMode.MOVE);
            ClipboardContent content = new ClipboardContent();

            int x = tableView.getSelectionModel().getSelectedCells().get(0).getColumn();
            int y = tableView.getSelectionModel().getSelectedCells().get(0).getRow();

            for(Event e:eventList) {
                if(e.getAblaufX() == x && e.getAblaufY() == y) {
                    //System.out.println("Event Abteilung: " + e.getAbteilung());
                    content.put(Config.SERIALIZED_MIME_TYPE, e.getId());
                }
            }

            db.setContent(content);
            event.consume();
        }
    });

    tableView.setOnDragDropped(new EventHandler<DragEvent>() {
        @Override
        public void handle(DragEvent event) {
            System.out.println("Drag Dropped!");

            Dragboard db = event.getDragboard();
             if (db.hasContent(Config.SERIALIZED_MIME_TYPE)) {
                 int draggedEventId = (Integer) db.getContent(Config.SERIALIZED_MIME_TYPE);
                 Event draggedEvent = null;
                 //System.out.println("Dragged Event ID: " + draggedEventId);
                 for(Event e:eventList) {
                     if(e.getId() == draggedEventId) {
                         draggedEvent = e;
                         eventMap.get(e).setAblaufX(ablaufX); // <-- HERE I NEED CELL INDEX
                         eventMap.get(e).setAblaufY(ablaufY); // <-- HERE I NEED ROW INDEX
                         //eventMap.put(new TablePos(draggedEvent.getAblaufX(), draggedEvent.getAblaufY()), draggedEvent);
                     }
                 }
                 if(draggedEvent != null) {
                     event.setDropCompleted(true);
                     event.consume();
                     System.out.println(draggedEvent.getText());
                 }
             }
        }
    });

    tableView.setOnDragOver(new EventHandler <DragEvent>() {
        public void handle(DragEvent event) {
            event.acceptTransferModes(TransferMode.ANY);
            event.consume();
        }
    });

I commented the tricky lines with " // <-- HERE I NEED CELL INDEX " and " // <-- HERE I NEED ROW INDEX "

On those lines, I need the columnIndex and the rowIndex of the dropped Cell (the new Cell)

You need to add the setOnDragDropped to the table cells instead of adding them to the entire TableView . Below is an MCVE on how to get the row and column index of a cell. The MCVE itself is not useful for anything else than to show how to get the row and column index of a cell. Please tell me if you need any further help.

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class MCVE extends Application {

    @Override
    public void start(Stage stage) {
        TableView<ObservableList<String>> table = new TableView<ObservableList<String>>();
        table.getSelectionModel().setCellSelectionEnabled(true);

        TableColumn<ObservableList<String>, String> col1 = new TableColumn<ObservableList<String>, String>();
        TableColumn<ObservableList<String>, String> col2 = new TableColumn<ObservableList<String>, String>();

        ObservableList<TableColumn<ObservableList<String>, String>> columns = FXCollections.observableArrayList(col1,
                col2);

        table.getColumns().addAll(columns);

        // For each column we set a cellFactory and a cellValueFactory.
        for (TableColumn<ObservableList<String>, String> col : columns) {
            col.setCellValueFactory(e -> new SimpleStringProperty("1"));

            // We need to set the cell factory so that we can create a cell and manipulate its behavior.
            col.setCellFactory(e -> {
                TableCell<ObservableList<String>, String> cell = new TableCell<ObservableList<String>, String>() {
                    @Override
                    public void updateItem(String item, boolean empty) {
                        // Make sure you call super.updateItem, or you might get really weird bugs.
                        super.updateItem(item, empty);
                        if (item == null || empty) {
                            setText(null);
                            setGraphic(null);
                        } else {
                            setText(item);
                            setGraphic(null);
                        }
                    }
                };

                // HERE IS HOW TO GET THE ROW AND CELL INDEX
                cell.setOnDragDetected(eh -> {
                    // Get the row index of this cell
                    int rowIndex = cell.getIndex();
                    System.out.println("Cell row index: " + rowIndex);

                    // Get the column index of this cell.
                    int columnIndex = cell.getTableView().getColumns().indexOf(cell.getTableColumn());
                    System.out.println("Cell column index: " + columnIndex);
                });

                return cell;
            });
        }

        ObservableList<ObservableList<String>> items = FXCollections.observableArrayList(
                FXCollections.observableArrayList("1", "2"), FXCollections.observableArrayList("1", "2"));

        table.setItems(items);

        BorderPane view = new BorderPane();
        view.setCenter(table);

        stage.setScene(new Scene(view));
        stage.show();
    }

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

You could get the the current cell using the pickResult of the Event to access the TableCell and use it to get the coordinates:

private static TableCell getCell(Node node) {
    // traverse to parent until TableCell is reached
    // or it's clear there's no TableCell in the hierarchy above node (root visited)
    while (node != null && !(node instanceof TableCell)) {
        node = node.getParent();
    }

    return (TableCell) node;
}
TableCell targetCell = getCell(event.getPickResult().getIntersectedNode());
if (targetCell != null) {
    int rowIndex = targetCell.getTableRow().getIndex();
    int columnIndex = columnToIndex(targetCell.getTableColumn());
    ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM