在拖放掉落过程中更改Javafx ListView中的光标



我有一个listView,我可以通过拖放来重新排列元素,并且可以正常工作,但是我想用自己的自定义替换两个默认图标。我已经尝试使用ListCell本身或其父母上的SetCursor(Cursor.Hand)SetCursor(New Imagecurs(image)),但只有在阻力期间,只有在此之后,这不是我想要的。有人知道该怎么做吗?

edit1:这个问题与如何创建可重新订购的ListView无关。它是关于如何在listView项目的拖放过程中更改默认光标。它不是
如何在javafx中创建可重新排序的tableView的重复,因为它在拖动n-drop期间也具有相同的默认光标图标。

EDIT2:根据我的发现,影响Windows和Linux OS:ES,而不是Mac OSX。

屏幕截图不允许图标

屏幕截图drag-n-drop允许图标

package sample;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.*;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Main extends Application {
    @Override
    public void start(Stage stage) throws Exception{
        Pane pane = new Pane();
        ObservableList<String> items = FXCollections.observableArrayList("test1", "test2", "test3", "test4");
        ListView<String> lw = new ListView<>();
        lw.setCellFactory(param -> new MyListCell());
        lw.setItems(items);
        pane.getChildren().add(lw);
        stage.setTitle("RearrangeListView");
        stage.setScene(new Scene(pane, 300, 150));
        stage.show();
    }
    private class MyListCell extends ListCell<String> {
        public MyListCell() {
            setOnDragDetected(event -> {
                if (getItem() == null) {
                    return;
                }
                if (event.getButton() == MouseButton.PRIMARY) {
                    WritableImage image = snapshot(new SnapshotParameters(), null);
                    Dragboard dragboard = startDragAndDrop(TransferMode.MOVE);
                    ClipboardContent content = new ClipboardContent();
                    content.putString("abc");
                    dragboard.setDragView(image);
                    dragboard.setContent(content);
                    //setCursor(Cursor.HAND);
                    event.consume();
                }
            });
            setOnDragOver(event -> {
                if (event.getGestureSource() != this && event.getDragboard().hasString()) {
                    event.acceptTransferModes(TransferMode.MOVE);
                }
                event.consume();
            });
            setOnDragEntered(event -> {
                if (event.getGestureSource() != this && event.getDragboard().hasString()) {
                    setOpacity(0.3);
                }
            });
            setOnDragExited(event -> {
                if (event.getGestureSource() != this && event.getDragboard().hasString()) {
                    setOpacity(1);
                }
            });
            setOnDragDropped(event -> {
                if (getItem() == null) {
                    return;
                }
                Dragboard db = event.getDragboard();
                boolean success = false;
                if (db.hasString()) {
                    ObservableList<String> items = getListView().getItems();
                    String source = ((MyListCell) event.getGestureSource()).getItem();
                    String target = ((MyListCell) event.getGestureTarget()).getItem();
                    int sourceIdx = items.indexOf(source);
                    int targetIdx = items.indexOf(target);
                    //swap
                    items.set(sourceIdx, target);
                    items.set(targetIdx, source);
                    success = true;
                }
                event.setDropCompleted(success);
                event.consume();
            });
            setOnDragDone(DragEvent::consume);
        }
        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || item == null) {
                setText(null);
            } else {
                setText(item);
            }
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}

好吧,我想现在了解我的误解。Javafx支持DragView和一个光标,并且同时显示它们。因此,我认为您要问的是如何仅显示DragView或DragView和自定义光标。

做到这一点的一种方法是将答案修改为:如何在Javafx中创建可重新订购的TableView,并进行以下更改:

private ImageCursor dragCursor;
. . .
// inside start()
dragCursor = new ImageCursor(
    new Image(
        "https://cdn2.iconfinder.com/data/icons/web/512/Cursor-512.png", 
        32, 32, true, true
    )
);
// at the end of setOnDragDetected()
getScene().setCursor(dragCursor);
// change setOnDragDone() to:
setOnDragDone(event -> {
    event.consume();
    getScene().setCursor(Cursor.DEFAULT);
});

如果您不想要光标而不是自定义图像光标,则可以致电:

getScene().setCursor(Cursor.NONE);

我在OS X上测试了该程序,在那里对我有用,您的里程可能会有所不同。请注意,光标处理可能会在操作系统之间有所不同(例如,在拖动时,在OS X上没有更改的情况下,我不会在Windows上看到的框,我只会得到一个默认的箭头光标除了DragView图像)。

只要您在场景中的对象周围拖动,上面的更改似乎可以正常工作。如果您在舞台外拖动,则光标将恢复回到默认的光标(我没有解决方案,因为Javafx一旦光标在场景之外就不允许控制光标)。

最新更新