我有一个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);
}
}