2016-12-05 78 views
1

我有一個listview,我可以通過拖放重新排列元素並且它工作正常,但是我想用我自己的自定義元素替換兩個默認圖標。我嘗試過在setCursor(Cursor.HAND)setCursor(新ImageCursor(圖像))上的ListCell本身或其父母,但沒有得到反映在拖動,只有後,這不是我想要的。任何人都知道如何去做這件事?在拖放過程中在JavaFx ListView中更改光標

編輯1:此問題與如何創建可重新排序的列表視圖無關。這是關於如何在拖放listview項目期間更改默認光標。它不是
How to create a reorder-able TableView in JavaFx的副本,因爲它在拖放時也具有非常相同的默認光標圖標。

EDIT2:影響Windows和Linux操作系統:ES根據我的調查結果,而不是Mac OS X的

screenshot drag-n-drop not allowed icon

screenshot drag-n-drop allowed icon

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

@jewelsea這個問題與如何創建可重新排序的listview無關。這是關於如何在拖放listview項目期間更改默認光標。 – jbilander

+0

@jewelsea謝謝,但我已經嘗試過您的示例,並且在拖動時遭受相同的默認光標(指向盒下的指針)。看看這個截圖[鏈接](https://dl.dropboxusercontent.com/u/60356891/screenshot_reorder_origami.png)該光標是我想改變的。 – jbilander

回答

0

OK,我想現在明白我的誤解。 JavaFX同時支持DragView和Cursor,並同時顯示它們。所以我想你所問的是如何只顯示DragView或DragView和自定義光標。要做到這一點

一種方法是修改答案:How to create a reorder-able TableView in JavaFx,有以下變化:如果你不想要的光標,而不是一個自定義圖像用光標

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不允許在光標經過場景後控制光標)。

+1

謝謝,我現在已經在我的Mac上測試了它,它在OS X上工作,但在Linux和Windows上不能工作,不知何故,這些操作系統似乎用自己的默認值覆蓋自定義光標。真的很煩人,但我想我必須忍受它。 – jbilander