在拖放过程中更改JavaFx ListView中的光标 [英] Change cursor in JavaFx ListView during drag and drop

查看:81
本文介绍了在拖放过程中更改JavaFx ListView中的光标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个列表视图,通过拖放可以重新排列元素,并且效果很好,但是我想用自己的自定义图标替换这两个默认图标.我已经尝试过在ListCell本身或其父级上使用setCursor(Cursor.HAND)setCursor(new ImageCursor(image)),但是在拖动过程中什么也没有反映出来,只是之后,这不是我想要的.有人知道该怎么做吗?

I have a listview where I made it possible to rearrange the elements via drag-and-drop and it works fine, however I want to replace the two default icons with my own custom ones. I have tried with i.e. setCursor(Cursor.HAND) setCursor(new ImageCursor(image)) on both the ListCell itself or its parents but nothing gets reflected during the drag, only after, which is not what I want. Anyone know how to go about this?

Edit1 :此问题与如何创建可重新排序的列表视图无关.它是关于如何在拖放列表视图项期间更改默认光标的.它不是
> JavaFx中可重新排序的TableView ,因为在拖放过程中它也具有非常相同的默认光标图标.

This question has nothing to do with how to create a reorder-able listview. It is about how to change the default cursor during drag-and-drop of a listview item. It is not a duplicate of
How to create a reorder-able TableView in JavaFx since it also has the very same default cursor icons during drag-n-drop.

Edit2 :根据我的发现,而不是Mac OS X,会影响Windows和Linux OS:

Affects Windows and Linux OS:es according to my findings, not Mac OS X.

屏幕快照不允许拖放图标

屏幕快照允许拖放图标

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和Cursor,并同时显示它们.因此,我想您要问的是如何仅显示DragView或同时显示DragView和自定义光标.

OK, I think understand my misunderstanding now. JavaFX supports both a DragView and a Cursor and it displays them both at the same time. So what I think what you are asking is how to show either only the DragView or both the DragView and a custom cursor.

一种方法是将答案修改为:如何在JavaFx中创建可重新排序的TableView ,并进行以下更改:

One way to do this is to modify the answer to: How to create a reorder-able TableView in JavaFx, with the following changes:

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);
});

如果您不需要光标,而不是自定义图像光标,则可以调用:

If you want no cursor rather than a custom image cursor, then you can just call:

getScene().setCursor(Cursor.NONE);

我在OS X上测试了该程序,并且该程序对我有用,您的工作量可能会有所不同.请注意,在不同的操作系统上,游标的处理方式可能有所不同(例如,在OS X上,如果不更改此答案,则在拖动时,我不会看到带有在Windows上看到的框的光标,而只是得到了默认的箭头光标除了DragView图像).

I tested the program on OS X and it worked for me there, your mileage may vary. Note that cursor handling may differ across operating systems (for instance, without the changes in this answer, on OS X, when dragging, I don't get the cursor with box that you are seeing on Windows, I just get a default arrow cursor in addition to the DragView image).

只要您在场景内的对象周围拖动,上述更改似乎就起作用.如果您将鼠标拖动到舞台外,则光标会恢复为默认光标(我没有解决办法,因为JavaFX不允许光标经过场景之外而对其进行控制).

The changes above seem to work as long as you are dragging around the object within the scene. If you drag outside the stage, then the cursor reverts back to the default cursor (I don't have a fix for that as JavaFX does not allow control of the cursor once it passes outside the scene).

这篇关于在拖放过程中更改JavaFx ListView中的光标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆