Tableview将一首歌曲连续拖放到侧栏javafx上的播放列表按钮

Tableview drag and drop a song in a row to a playlist button on the side bar javafx

我有一个 javafx TableView,其中填充了一个名为 Song 的 class。我的边框窗格中有一个边栏,其中填充了代表 class 称为播放列表的按钮。我的(目前是基本的)UI 看起来像这样:

我想做的是,如果我将一首歌曲拖放到左侧的其中一个按钮中,它就会将该歌曲添加到播放列表中。此外,我在互联网上查看并搜索了答案,但没有找到任何有用的信息。话虽如此,请不要 link 我做某事。我已经尝试实施以下 link 中的代码:http://docs.oracle.com/javase/8/javafx/events-tutorial/drag-drop.htm#CHDJFJDH 如果您有任何建议,请帮助我!谢谢!

更新: 这是我的代码,我的命名约定很容易理解:

    musicTable.setOnMouseClicked(new EventHandler<MouseEvent>() { //click
        @Override
        public void handle(MouseEvent event) {
            if (event.getClickCount() == 2) { // double click

                Song selected =   (Song)musicTable.getSelectionModel().getSelectedItem();
                dragged = selected;
                if (selected != null) {
                    System.out.println("select : " + selected);

                }
            }
        }
    });

    musicTable.setOnDragDetected(new EventHandler<MouseEvent>() { //drag
        @Override
        public void handle(MouseEvent event) {
            // drag was detected, start drag-and-drop gesture
            Song selected = (Song)musicTable.getSelectionModel().getSelectedItem();
            dragged = selected;
            if (selected != null) {

                Dragboard db = musicTable.startDragAndDrop(TransferMode.ANY);
                ClipboardContent content = new ClipboardContent();
                content.putString(selected.pointer.toString());
                db.setContent(content);
                event.consume();
            }
        }
    });

    musicTable.setOnDragOver(new EventHandler<DragEvent>() {
        @Override
        public void handle(DragEvent event) {
            // data is dragged over the target
            Dragboard db = event.getDragboard();
            if (event.getDragboard().hasString()) {
                event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
            }
            event.consume();
        }
    });
    musicTable.setOnDragDropped(new EventHandler<DragEvent>() {
        @Override
        public void handle(DragEvent event) {
            Dragboard db = event.getDragboard();
            boolean success = false;
            if (event.getDragboard().hasString()) {

                String text = db.getString();
                //tableContent.add(text);
                //musicTable.setItems(tableContent);

                success = true;
            }
            event.setDropCompleted(success);
            event.consume();
        }
    });
    playlistTable.setRowFactory(cb -> {
        TableRow<Playlist> row = new TableRow<>();
        row.setOnMouseClicked(ev -> {
            musicTable.setItems(row.getItem().playlist);

            row.setOnDragDropped( new EventHandler<DragEvent>() {
                @Override
                public void handle(DragEvent event) {
                    boolean success = false;

                    row.getItem().add(dragged);
                    System.out.println("ACCEPED TRANSFER");

                    success = true;

                    event.setDropCompleted(success);
                    event.consume();
                }
            });
        });
        return row;

    });

dragged 是一首跟踪哪首歌被拖动的歌曲,如果您有任何其他方法请告诉我,musicTable 是我从中拖动的,播放列表 table 是我的位置'拖到.

好的,这是我能创建的最小示例:

@Override
public void start(Stage primaryStage) throws IOException {

    ObservableList<String> tableData = FXCollections
            .observableList(IntStream.range(0, 1000)
                    .mapToObj(Integer::toString)
                    .collect(Collectors.toList()));
    TableView<String> stringTable = new TableView<>(tableData);

    TableColumn<String, String> column1 = new TableColumn<>();
    column1.setCellValueFactory(cb -> new ReadOnlyStringWrapper(cb
            .getValue()));
    stringTable.getColumns().add(column1);

    stringTable.setRowFactory(cb -> {
        TableRow<String> row = new TableRow<>();
        row.setOnDragDetected(ev -> {
            Dragboard db = row.startDragAndDrop(TransferMode.COPY);

            ClipboardContent content = new ClipboardContent();
            content.putString(row.getItem());
            db.setContent(content);

            ev.consume();
        });
        return row;
    });

    VBox leftSide = new VBox();
    leftSide.setPrefWidth(300);

    leftSide.setOnDragOver(ev -> {
        if (ev.getGestureSource() != leftSide && ev.getDragboard().hasString()) {
            ev.acceptTransferModes(TransferMode.COPY);
        }
        ev.consume();
    });

    leftSide.setOnDragDropped(ev -> {
        Dragboard db = ev.getDragboard();
        boolean success = false;
        if (db.hasString()) {
            Label label = new Label(db.getString());
            leftSide.getChildren().add(label);
            success = true;
        }
        ev.setDropCompleted(success);
        ev.consume();
    });

    BorderPane root = new BorderPane(stringTable);
    root.setLeft(leftSide);

    Scene scene = new Scene(root, 700, 400);
    primaryStage.setScene(scene);
    primaryStage.show();
}

这是一个 BorderPane,中间是 TableView,左边是 VBox

现在我添加了您请求的拖放处理程序,这样您就可以将行(因此这是在 row factory 中完成的)拖到左侧,在那里它们作为新的 Label 添加到VBox 为新 children.


编辑:第二个示例,其中 ListView 作为放置目标:

@Override
public void start(Stage primaryStage) {

    ObservableList<String> tableData = FXCollections
            .observableList(IntStream.range(0, 1000)
                    .mapToObj(Integer::toString)
                    .collect(Collectors.toList()));
    TableView<String> stringTable = new TableView<>(tableData);

    TableColumn<String, String> column1 = new TableColumn<>();
    column1.setCellValueFactory(cb -> new ReadOnlyStringWrapper(cb
            .getValue()));
    stringTable.getColumns().add(column1);

    stringTable.setRowFactory(cb -> {
        TableRow<String> row = new TableRow<>();
        row.setOnDragDetected(ev -> {
            Dragboard db = row.startDragAndDrop(TransferMode.COPY);

            ClipboardContent content = new ClipboardContent();
            content.putString(row.getItem());
            db.setContent(content);

            ev.consume();
        });
        return row;
    });

    ObservableList<String> leftSideItems = FXCollections
            .observableList(IntStream.range(0, 1000)
                    .mapToObj(Integer::toString)
                    .collect(Collectors.toList()));
    ListView<String> leftSideDropTarget = new ListView<String>(
            leftSideItems);
    leftSideDropTarget.setPrefWidth(200);
    leftSideDropTarget.setCellFactory(cb -> {
        ListCell<String> cell = new TextFieldListCell<>();

        cell.setOnDragOver(ev -> {
            if (ev.getGestureSource() != cell
                    && ev.getDragboard().hasString()) {
                ev.acceptTransferModes(TransferMode.COPY);
            }
            ev.consume();
        });

        cell.setOnDragDropped(ev -> {
            Dragboard db = ev.getDragboard();
            boolean success = false;
            if (db.hasString()) {
                cell.setText("Got Item: " + db.getString());
                success = true;
            }
            ev.setDropCompleted(success);
            ev.consume();
        });

        return cell;

    });

    BorderPane root = new BorderPane(stringTable);
    root.setLeft(leftSideDropTarget);

    Scene scene = new Scene(root, 700, 400);
    primaryStage.setScene(scene);
    primaryStage.show();
}