将项目拖放到TableView中,在现有行之间

时间:2016-04-22 04:48:19

标签: javafx drag-and-drop javafx-8

表包含以下行(例如,一列):

A
B
C

我正在试图找出如何将项目拖入其中,并将其放置在现有的行B和C之间。

我能够执行拖放操作,导致在表格末尾添加一个项目,但根据我释放鼠标按钮的位置,我无法弄清楚如何将它放在行之间。

1 个答案:

答案 0 :(得分:2)

创建一个rowFactory生成TableRow,接受手势并根据鼠标位置决定是否在行之前或之后添加项目:

@Override
public void start(Stage primaryStage) {
    TableView<Item> table = new TableView<>();

    Button button = new Button("A");

    // d&d source providing next char
    button.setOnDragDetected(evt -> {
        Dragboard db = button.startDragAndDrop(TransferMode.MOVE);
        ClipboardContent content = new ClipboardContent();
        content.putString(button.getText());
        db.setContent(content);
    });
    button.setOnDragDone(evt -> {
        if (evt.isAccepted()) {
            // next char
            button.setText(Character.toString((char) (button.getText().charAt(0) + 1)));
        }
    });

    // accept for empty table too
    table.setOnDragOver(evt -> {
        if (evt.getDragboard().hasString()) {
            evt.acceptTransferModes(TransferMode.COPY_OR_MOVE);
        }
        evt.consume();
    });
    table.setOnDragDropped(evt -> {
        Dragboard db = evt.getDragboard();
        if (db.hasString()) {
            table.getItems().add(new Item(db.getString()));
            evt.setDropCompleted(true);
        }
        evt.consume();
    });

    TableColumn<Item, String> col = new TableColumn<>("value");
    col.setCellValueFactory(new PropertyValueFactory<>("value"));
    table.getColumns().add(col);

    // let rows accept drop too
    table.setRowFactory(tv -> {
        TableRow<Item> row = new TableRow();
        row.setOnDragOver(evt -> {
            if (evt.getDragboard().hasString()) {
                evt.acceptTransferModes(TransferMode.COPY_OR_MOVE);
            }
            evt.consume();
        });
        row.setOnDragDropped(evt -> {
            Dragboard db = evt.getDragboard();
            if (db.hasString()) {
                Item item = new Item(db.getString());
                if (row.isEmpty()) {
                    // row is empty (at the end -> append item)
                    table.getItems().add(item);
                } else {
                    // decide based on drop position whether to add the element before or after
                    int offset = evt.getY() > row.getHeight() / 2 ? 1 : 0;
                    table.getItems().add(row.getIndex() + offset, item);
                    evt.setDropCompleted(true);
                }
            }
            evt.consume();
        });
        return row;
    });

    Scene scene = new Scene(new VBox(button, table));

    primaryStage.setScene(scene);
    primaryStage.show();
}
public class Item {

    public Item() {
    }

    public Item(String value) {
        this.value.set(value);
    }

    private final StringProperty value = new SimpleStringProperty();

    public String getValue() {
        return value.get();
    }

    public void setValue(String val) {
        value.set(val);
    }

    public StringProperty valueProperty() {
        return value;
    }

}