我正在尝试为 ListView 实现拖放,其中每个单元格都是一个 GridPane。所以,我只是制作相应 GridPane 的快照并设置为拖动视图。
WritableImage im = rootPane.snapshot(null, null);
dragboard.setDragView(im);
问题是拖动视图图像的大小以某种方式缩小了,我不知道为什么会这样。
我尝试缩放快照图像,但没有成功。
WritableImage writableImage = new WritableImage((int)(5 * getWidth()), (int)(5 * getHeight()));
SnapshotParameters sp = new SnapshotParameters();
sp.setTransform(Transform.scale(5, 5));
WritableImage im = rootPane.snapshot(sp, writableImage);
谁能解释一下拖动时如何显示实际图像大小。
编辑:
最小的可重现示例。我还注意到拖动视图的大小取决于...场景大小。较大的场景尺寸较低的拖动视图将
public class Launcher extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane pane = new BorderPane();
ListView<Foo> fooList = new ListView<>();
pane.setCenter(fooList);
fooList.setCellFactory(list -> new FooCell());
fooList.getItems().setAll(List.of(new Foo("1"), new Foo("2"), new Foo("3"), new Foo("4")));
Scene scene = new Scene(pane, 1400, 900);
primaryStage.setTitle("Demo");
primaryStage.setScene(scene);
primaryStage.setOnCloseRequest(t -> Platform.exit());
primaryStage.show();
}
static class Foo {
public String a;
public Foo(String a) {
this.a = a;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Foo foo = (Foo) o;
return a.equals(foo.a);
}
@Override
public int hashCode() {
return a.hashCode();
}
}
static class FooCell extends ListCell<Foo> {
private AnchorPane rootPane;
private GridPane gridPane;
private Region dragHandle;
private TextField textField;
private HBox hbox;
public FooCell() {
ListCell<Foo> thisCell = this;
rootPane = new AnchorPane();
gridPane = new GridPane();
gridPane.setPrefHeight(40);
AnchorPane.setTopAnchor(gridPane, 0d);
AnchorPane.setRightAnchor(gridPane, 0d);
AnchorPane.setBottomAnchor(gridPane, 0d);
AnchorPane.setLeftAnchor(gridPane, 0d);
rootPane.getChildren().setAll(gridPane);
dragHandle = new Region();
dragHandle.setMinWidth(30);
setOnDragDetected(event -> {
if (getItem() == null) return;
ObservableList<Foo> items = getListView().getItems();
Dragboard dragboard = startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(getItem().a);
dragboard.setDragView(gridPane.snapshot(null, null));
dragboard.setContent(content);
event.consume();
});
setOnDragOver(event -> {
if (event.getGestureSource() != thisCell && event.getDragboard().hasString()) {
event.acceptTransferModes(TransferMode.MOVE);
}
event.consume();
});
setOnDragEntered(event -> {
if (event.getGestureSource() != thisCell && event.getDragboard().hasString()) {
setOpacity(0.3);
}
});
setOnDragExited(event -> {
if (event.getGestureSource() != thisCell && event.getDragboard().hasString()) {
setOpacity(1);
}
});
setOnDragDropped(event -> {
if (getItem() == null) return;
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
ObservableList<Foo> items = getListView().getItems();
int draggedIdx = items.indexOf(new Foo(db.getString()));
int thisIdx = items.indexOf(getItem());
items.set(draggedIdx, getItem());
items.set(thisIdx, new Foo(db.getString()));
List<Foo> itemscopy = new ArrayList<>(getListView().getItems());
getListView().getItems().setAll(itemscopy);
success = true;
}
event.setDropCompleted(success);
event.consume();
});
setOnDragDone(DragEvent::consume);
textField = new TextField();
hbox = new HBox();
ColumnConstraints col0 = new ColumnConstraints();
col0.setHgrow(Priority.NEVER);
gridPane.add(dragHandle, 0, 0, 1, 10);
ColumnConstraints col1 = new ColumnConstraints();
col1.setHgrow(Priority.ALWAYS);
gridPane.add(textField, 1, 0, 1, 1);
gridPane.add(hbox, 1, 1, 10, 1);
gridPane.getColumnConstraints().addAll(col0, col1);
}
@Override
protected void updateItem(Foo item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
return;
}
textField.setText(item.a);
setGraphic(rootPane);
}
}
}
EDIT2(发现问题):
是操作系统(或者更准确地说是显示管理器)将拖动的图像缩小。似乎 JavaFX 使用的 GTK 后端对拖动的图像实施了某种限制。如果图像宽度大于 300-350 像素,它将被缩小。我发现这只是试图在我的电子邮件客户端中拖动各种图片。小图像或中图像不会改变,但会缩放较大的图像。我所说的取决于场景大小是正确的,但这里没有魔法。更改场景大小时,也会更改目标节点大小。当它的宽度接近 300px.. 是的,很明显,但我没有注意。
通常我的问题是我想拖动宽度较大但高度较低的图像。这就是为什么缩放看起来如此丑陋/由于超低字体大小而使文本无法阅读的原因。有趣的是,Electron 没有这样的问题。要么 Chromium 不使用 GTK API 进行拖动,要么 DOM 根据定义不存在此类问题。