I am working on a sample application with 2 list views i.e. players and team, and implement drop and drop such that players can be dropped from one list view to the other. Everything is working as expected when there is single selection model is enabled on the source list view. However, if I enabled Multiple selection model and drag 2 or more rows from source list view to target list view, seeing the following exception after the drop is completed.
Exception:
java.lang.IllegalArgumentException: Only serializable objects or ByteBuffer can be used as data with data format [subListPlayers]
at com.sun.javafx.tk.quantum.QuantumClipboard.putContent(QuantumClipboard.java:513)
at javafx.scene.input.Clipboard.setContent(Clipboard.java:230)
1) What should be the DataFormat used in order to be able to drag and drop multiple rows? Looks like we do not have for Object type, so I have created the following one which does not solve the problem.
private DataFormat dataFormat = new DataFormat("subListPlayers");
2) I have made changes to support serialization on the data object which also does not seem to solve the issue. Tried by implementing Serializable interface as well as by implementing Externalize interface.
Can someone please guide if there is an easy way to implement this behavior?
Code:
public class Player
{
private String name;
public Player(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Player player = (Player) o;
if (name != null ? !name.equals(player.name) : player.name != null) return false;
return true;
}
@Override
public int hashCode()
{
return name != null ? name.hashCode() : 0;
}
}
public class JavaFXDnDApplication extends Application
{
private static final ListView<Player> playersListView = new ListView<Player>();
private static final ObservableList<Player> playersList = FXCollections.observableArrayList();
private static final ListView<Player> teamListView = new ListView<Player>();
private static final GridPane rootPane = new GridPane();
private DataFormat dataFormat = new DataFormat("subListPlayers");
public static void main(String[] args)
{
launch(args);
}
@Override
public void start(Stage primaryStage)
{
primaryStage.setTitle("Drag and Drop Application");
initializeComponents();
initializeListeners();
buildGUI();
populateData();
primaryStage.setScene(new Scene(rootPane, 400, 325));
primaryStage.show();
}
private void initializeListeners()
{
playersListView.setOnDragDetected(new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent event)
{
System.out.println("setOnDragDetected");
Dragboard dragBoard = playersListView.startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
// content.putString(playersListView.getSelectionModel().getSelectedItem().getName());
content.put(dataFormat, playersListView.getSelectionModel().getSelectedItems());
dragBoard.setContent(content);
}
});
teamListView.setOnDragOver(new EventHandler<DragEvent>()
{
@Override
public void handle(DragEvent dragEvent)
{
dragEvent.acceptTransferModes(TransferMode.MOVE);
}
});
teamListView.setOnDragDropped(new EventHandler<DragEvent>()
{
@Override
public void handle(DragEvent dragEvent)
{
// String player = dragEvent.getDragboard().getString();
// ObservableList<Player> player = (ObservableList<Player>) dragEvent.getDragboard().getContent(dataFormat);
String player = dragEvent.getDragboard().getString();
teamListView.getItems().addAll(new Player(player));
playersList.remove(new Player(player));
dragEvent.setDropCompleted(true);
}
});
}
private void buildGUI()
{
// rootPane.setGridLinesVisible(true);
rootPane.setPadding(new Insets(10));
rootPane.setPrefHeight(30);
rootPane.setPrefWidth(100);
rootPane.setVgap(20);
rootPane.setHgap(20);
rootPane.add(playersListView, 0, 0);
rootPane.add(teamListView, 1, 0);
}
private void populateData()
{
playersList.addAll(
new Player("Adam"), new Player("Alex"), new Player("Alfred"), new Player("Albert"),
new Player("Brenda"), new Player("Connie"), new Player("Derek"), new Player("Donny"),
new Player("Lynne"), new Player("Myrtle"), new Player("Rose"), new Player("Rudolph"),
new Player("Tony"), new Player("Trudy"), new Player("Williams"), new Player("Zach")
);
playersListView.setItems(playersList);
}
private void initializeComponents()
{
playersListView.setPrefSize(250, 290);
playersListView.setEditable(true);
playersListView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
playersListView.setCellFactory(new Callback<ListView<Player>, ListCell<Player>>()
{
@Override
public ListCell<Player> call(ListView<Player> playerListView)
{
return new ListCell<Player>()
{
@Override
protected void updateItem(Player player, boolean b)
{
super.updateItem(player, b);
if (player != null)
{
setText(player.getName());
}
}
};
}
});
teamListView.setPrefSize(250, 290);
teamListView.setEditable(true);
teamListView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
teamListView.setCellFactory(new Callback<ListView<Player>, ListCell<Player>>()
{
@Override
public ListCell<Player> call(ListView<Player> playerListView)
{
return new ListCell<Player>()
{
@Override
protected void updateItem(Player player, boolean b)
{
super.updateItem(player, b);
if (player != null)
{
setText(player.getName());
}
}
};
}
});
}
}