在TreeTableView中拖放

时间:2019-03-09 18:22:57

标签: javafx drag-and-drop treetableview

我有一个TreeTableView控件,我想拖动它们的项目以个性化的方式对它们进行重新排序,并且我想显示一条线,指示执行该操作时它们将要去的地方。我的问题是,一旦绘制了线条,它就会保留,尽管它不再有效,好像有必要刷新控件的内容并且我不知道如何解决它。我在这里留下一个我所拥有的功能性例子:

package treetableviewdnd;

import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableRow;
import javafx.scene.control.TreeTableView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TreeTableViewDND extends Application {

    private static final DataFormat SERIAL = new DataFormat("application/x-java-serialized-object");       
    private TreeItem<Map<String, Object>> root;
    private TreeTableView<Map<String, Object>> tree;

    @Override
    public void start(Stage primaryStage) throws Exception {
        VBox outer = new VBox();

        root = new TreeItem<>();
        tree = new TreeTableView<>(root);
        tree.setShowRoot(false);
        tree.setRowFactory(this::rowFactory);
        addColumn("Region", "region");
        addColumn("Population", "population");
        setupData();

        outer.getChildren().addAll(tree);
        Scene scene = new Scene(outer, 640, 480);
        primaryStage.setScene(scene);
        primaryStage.show();
    }      

    private TreeTableRow<Map<String, Object>> rowFactory(TreeTableView<Map<String, Object>> view) {
        TreeTableRow<Map<String, Object>> row = new TreeTableRow<>();
        row.setOnDragDetected(event -> {
            if (!row.isEmpty()) {
                Dragboard db = row.startDragAndDrop(TransferMode.MOVE);
                db.setDragView(row.snapshot(null, null));
                ClipboardContent cc = new ClipboardContent();
                cc.put(SERIAL, row.getIndex());
                db.setContent(cc);
                event.consume();
            }
        });

        row.setOnDragOver(event -> {
            Dragboard db = event.getDragboard();
            row.setStyle("-fx-border-width: 0 0 0 0;");
            if (acceptable(db, row)) {
                row.setStyle("-fx-border-color: red; -fx-border-width: 0 0 2 0; -fx-padding: 3 3 1 3");
                event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                event.consume();
            }
        });

        row.setOnDragDropped(event -> {
            Dragboard db = event.getDragboard();
            if (acceptable(db, row)) {
                int index = (Integer) db.getContent(SERIAL);
                TreeItem item = tree.getTreeItem(index);
                item.getParent().getChildren().remove(item);
                getTarget(row).getChildren().add(item);
                event.setDropCompleted(true);
                tree.getSelectionModel().select(item);
                event.consume();
            }            
        });

        return row;
    }

    private boolean acceptable(Dragboard db, TreeTableRow<Map<String, Object>> row) {
        boolean result = false;
        if (db.hasContent(SERIAL)) {
            int index = (Integer) db.getContent(SERIAL);
            if (row.getIndex() != index) {
                TreeItem target = getTarget(row);
                TreeItem item = tree.getTreeItem(index);
                result = !isParent(item, target);
            }
        }
        return result;
    }

    private TreeItem getTarget(TreeTableRow<Map<String, Object>> row) {
        TreeItem target = tree.getRoot();
        if (!row.isEmpty()) {
            target = row.getTreeItem();
        }
        return target;
    }

    private boolean isParent(TreeItem parent, TreeItem child) {
        boolean result = false;
        while (!result && child != null) {
            result = child.getParent() == parent;
            child = child.getParent();
        }
        return result;
    }

    private void setupData() {
        TreeItem<Map<String, Object>> europe = createItem(root, "Europe", 742500000L);
        createItem(europe, "Germany ", 81276000);
        createItem(europe, "Finland ", 2703000);
        createItem(europe, "Estonia ", 1096300);        
        TreeItem<Map<String, Object>> america = createItem(root, "America", 953700000L);
        createItem(america, "Argentina", 3189000L);
        createItem(america, "Chile", 223000L); 
        createItem(america, "Mexico", 12230000L);
    }

    private TreeItem<Map<String, Object>> createItem(TreeItem<Map<String, Object>> parent, String region, long population) {
        TreeItem<Map<String, Object>> item = new TreeItem<>();
        Map<String, Object> value = new HashMap<>();
        value.put("region",  region);
        value.put("population", population);
        item.setValue(value);
        parent.getChildren().add(item);
        item.setExpanded(true);
        return item;
    }

protected void addColumn(String label, String dataIndex) {
        TreeTableColumn<Map<String, Object>, String> column = new TreeTableColumn<>(label);
        column.setPrefWidth(150);
        column.setCellValueFactory(
            (TreeTableColumn.CellDataFeatures<Map<String, Object>, String> param) -> {
                ObservableValue<String> result = new ReadOnlyStringWrapper("");
                if (param.getValue().getValue() != null) {
                    result = new ReadOnlyStringWrapper("" + param.getValue().getValue().get(dataIndex));
                }
                return result;
            }
        );        
        tree.getColumns().add(column);
    }

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

}

0 个答案:

没有答案