2 Replies Latest reply on Oct 28, 2013 8:04 PM by 935510

    Issue with Drag/Drop of multiple rows from ListView

    935510

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

                        }

                     }

                  };

               }

            });

         }

      }

       

      
      
        • 1. Re: Issue with Drag/Drop of multiple rows from ListView
          James_D

          Yeah, this is a pain. I filed https://javafx-jira.kenai.com/browse/RT-29082 a while back. Go ahead and vote for it if you are inclined...

           

          I think the issue in your case is that the observable list provided by MultipleSelectionModel.getSelectedItems() is not Serializable. So even if you make your Player class Serializable, the list itself isn't. The first thing I would try, I think, is to make Player implement Serializable and then pass in an ArrayList instead of the observable list. So you can do

          content.put(dataFormat, new ArrayList<Player>(playersListView.getSelectionModel().getSelectedItems()));
          

          and

          List<Player> player = (List<Player>) dragEvent.getDragboard().getContent(dataFormat);
          teamListView.getItems().addAll(player);
          


          If that doesn't work, a workaround is just to store the "dragged list" in a property:


          final ListProperty<Player> draggedPlayers = new SimpleListProperty<Player>();
          //...
          // Drag detected handler:
          content.putString("players");
          draggedPlayers.set(playersListView.getSelectionMode().getSelectedItems());
          
          
          // Drag dropped handler:
          if (dragboard.hasString() && dragboard.getString().equals("players")) {
               teamListView.getItems().addAll(draggedPlayers.get());
               draggedPlayers.set(null);
          }
          




          • 2. Re: Issue with Drag/Drop of multiple rows from ListView
            935510

            Thanks. Appreciate it.

             

            Yes, ObservableList is not serializable in this case.