如何在一个列表视图中拖放
我只有一个列表视图(编辑“播放器”)
我的要求是在同一个播放器列表中上下移动
请找到我用过的代码
(不是:我使用jdk 1.7和默认的javafx)
示例:(player = listView)
listView.setOnDragDetected(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Dragboard dragBoard = listView.startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(listView.getSelectionModel().getSelectedItem().getValue());
dragBoard.setContent(content);
}
});
listView.setOnDragDone(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent dragEvent) {
System.out.println("setOnDragDone left");
}
});
listView.setOnDragEntered(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent dragEvent) {
System.out.println("setOnDragEntered left");
}
});
listView.setOnDragExited(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent dragEvent) {
System.out.println("setOnDragExited left");
listView.setBlendMode(null);
}
});
listView.setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent dragEvent) {
System.out.println("setOnDragOver left");
dragEvent.acceptTransferModes(TransferMode.MOVE);
}
});
listView.setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent dragEvent) {
String context = dragEvent.getDragboard().getString();
dragEvent.setDropCompleted(true);
}
}
});
我是javafx的新手
请你帮忙解决这个问题
答案 0 :(得分:3)
不要在ListView
上注册拖动处理程序:您将无法知道拖动开始和结束的单元格。相反,您需要在单元格上注册处理程序。细节有点棘手,但基本的想法是创建一个单元工厂,在其中创建自定义单元格;在这里你可以设置拖放处理程序。
以下是一个例子:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class DragAndDropListView extends Application {
@Override
public void start(Stage primaryStage) {
final ListView<String> listView = new ListView<>();
for (int i=1; i<=20; i++) {
listView.getItems().add("Item "+i);
}
final IntegerProperty dragFromIndex = new SimpleIntegerProperty(-1);
listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> lv) {
final ListCell<String> cell = new ListCell<String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
setText(item);
}
}
};
cell.setOnDragDetected(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (! cell.isEmpty()) {
dragFromIndex.set(cell.getIndex());
Dragboard db = cell.startDragAndDrop(TransferMode.MOVE);
ClipboardContent cc = new ClipboardContent();
cc.putString(cell.getItem());
db.setContent(cc);
// Java 8 only:
// db.setDragView(cell.snapshot(null, null));
}
}
});
cell.setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
if (dragFromIndex.get() >= 0 && dragFromIndex.get() != cell.getIndex()) {
event.acceptTransferModes(TransferMode.MOVE);
}
}
});
// highlight drop target by changing background color:
cell.setOnDragEntered(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
if (dragFromIndex.get() >= 0 && dragFromIndex.get() != cell.getIndex()) {
// should really set a style class and use an external style sheet,
// but this works for demo purposes:
cell.setStyle("-fx-background-color: gold;");
}
}
});
// remove highlight:
cell.setOnDragExited(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
cell.setStyle("");
}
});
cell.setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
int dragItemsStartIndex ;
int dragItemsEndIndex ;
int direction ;
if (cell.isEmpty()) {
dragItemsStartIndex = dragFromIndex.get();
dragItemsEndIndex = listView.getItems().size();
direction = -1;
} else {
if (cell.getIndex() < dragFromIndex.get()) {
dragItemsStartIndex = cell.getIndex();
dragItemsEndIndex = dragFromIndex.get() + 1 ;
direction = 1 ;
} else {
dragItemsStartIndex = dragFromIndex.get();
dragItemsEndIndex = cell.getIndex() + 1 ;
direction = -1 ;
}
}
List<String> rotatingItems = listView.getItems().subList(dragItemsStartIndex, dragItemsEndIndex);
List<String> rotatingItemsCopy = new ArrayList<>(rotatingItems);
Collections.rotate(rotatingItemsCopy, direction);
rotatingItems.clear();
rotatingItems.addAll(rotatingItemsCopy);
dragFromIndex.set(-1);
}
});
cell.setOnDragDone(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
dragFromIndex.set(-1);
listView.getSelectionModel().select(event.getDragboard().getString());
}
});
return cell ;
}
});
BorderPane root = new BorderPane();
root.setCenter(listView);
Scene scene = new Scene(root, 250, 400);
scene.getStylesheets().add(getClass().getResource("drag-and-drop-list.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这将使您能够拖动任何元素并将其拖放到任何其他元素上。例如,拖动列表中的第三项
并将其放在第一个项目上会产生以下结果:
在Java 8中,您还可以添加行
db.setDragView(cell.snapshot(null, null));
到setOnDragDetected(...)
方法以获得更好的视觉效果。