Hello guys. Today I’ve got some free time to blog. I have made small chemical solution for making these things happen. I was thinking that most of the game developers really need this type of system even more in the content management system also this kind of stuffs are very useful So I’ve planned to blogged about this (Drag n Drop Cell).
Let’s first look over how the things works for the Draggable of list cell.
The above figure is just the concept which I’ve predicted. You can use your own too But in this post I’m doing all stuffs by this algorithm.By the help of that algorithm I’ve made the things sucess.
First let’s start with the custom cell I’ve given that cell name as ListCellX.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
" ] /** * * @author Narayan */ public class ListCellX<T> extends ListCell<T> implements ChangeListener<Number>{ //This attribute is for making my drag n drop totally private public static DataFormat dataFormat = new DataFormat("mycell"); //I keep track of which item is now currently being dragged private static IntegerProperty ind = new SimpleIntegerProperty(-1); //I can hold the dragged item Object for some time. private static Object temp = null; //I'm the item Object keeper. Come to me if you need any item private ObservableList items; //I'm the one who can make things draggable private boolean draggable =true; //When any cell is dragged then I'm being named which index to be deleted private static int toBeDeleted = -1; //It's my class of fashion private String styleclass = "list-cellx"; //I can make things happen private void setDraggable(boolean b){ draggable = b; } //Call me if you want to verify for drag work public boolean isDraggable(){ return draggable; } //Basic mind making I'm adding up to the cell so that //those cell can learn how to take place of another cell public void init(ObservableList itms){ items = itms; this.indexProperty().addListener(this); this.getStyleClass().add(styleclass); //this.setStyle("-fx-background-color : red; "); } /** * I'm always ready for update * @param item * @param empty */ @Override public void updateItem(T item,boolean empty){ super.updateItem(item, empty); if(item!=null){ if(getIndex() == ind.get()){ InnerShadow is = new InnerShadow(); is.setOffsetX(1.0); is.setColor(Color.web("#666666")); is.setOffsetY(1.0); setEffect(is); } } } /** * If any changes happens for my 'items' I'm watching on you. * @param arg0 * @param arg1 * @param arg2 */ @Override public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) { //Wait are you draggable ? and you are on our company? if(isDraggable() && getIndex() < items.size()){ //If some kind of mice will click on your then do this setOnMouseClicked(new EventHandler<MouseEvent>(){ @Override public void handle(MouseEvent arg0) { getListView().scrollTo(getIndex()); } }); //Some body is dragging and they are on me. setOnDragEntered(new EventHandler<DragEvent>(){ @Override public void handle(DragEvent arg0) { if(arg0.getTransferMode() == TransferMode.MOVE){ String cellS = (String)arg0.getDragboard().getContent(dataFormat); Object o = arg0.getDragboard().getContent(dataFormat); if(toBeDeleted == getIndex()){ return; } if(toBeDeleted != -1){ items.remove(toBeDeleted); toBeDeleted = -1; } if(o != null && temp != null ){ if(getIndex() < items.size()) items.add(getIndex(),(T)temp); else if(getIndex() == items.size()) items.add((T)temp); } ind.set(getIndex()); } } }); //Some body just went off dragging from my cell. setOnDragExited(new EventHandler<DragEvent>(){ @Override public void handle(DragEvent arg0) { if(arg0.getTransferMode() == TransferMode.MOVE){ Object o = arg0.getDragboard().getContent(dataFormat); if(o != null){ setEffect(null); if(getIndex()<items.size()) toBeDeleted = getIndex(); } } } }); //OMG! That mice pressed me. I need to take some action pressedProperty().addListener(new ChangeListener<Boolean>(){ @Override public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) { InnerShadow is = new InnerShadow(); is.setOffsetX(1.0); is.setColor(Color.web("#666666")); is.setOffsetY(1.0); if(!arg2){ setEffect(null); } }); //Ok I'm off I'm Over stop dragging me man! setOnDragOver(new EventHandler<DragEvent>(){ @Override public void handle(DragEvent event) { System.out.println("Over"); event.acceptTransferModes(TransferMode.MOVE); } }); //Hey hey hey You are dragging me! Wait I need to call somebody setOnDragDetected(new EventHandler<MouseEvent>(){ @Override public void handle(MouseEvent event) { Dragboard db = getListView().startDragAndDrop(TransferMode.MOVE); temp = items.get(getIndex()); toBeDeleted = getIndex(); Object item = items.get(getIndex()); /* Put a string on a dragboard */ ClipboardContent content = new ClipboardContent(); if(item != null) content.put(dataFormat,item.toString()); else content.put(dataFormat,"XData"); db.setContent(content); event.consume(); } }); } } } |
FYI I’ve highlighted the codes above. I think you can easily understand the code. I’ve done some commented for codes which could be more clear enough too.
Ok Now After we build our Customized ListCellX we can now easily embed this Cell in our ListView by implementing the cellfactory of specified ListView. You must make sure that you have called the init(ObservableList). A sample work over this cell is given here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
" ] <your listView>.setCellFactory(new Callback<ListView<Person>,ListCell<Person>> (){ @Override public ListCell<Person> call(ListView<Person> arg0) { //My cell is on my way to call ListCellX<Person> cell = new ListCellX<Person>(){ @Override public void updateItem(Person item,boolean empty){ super.updateItem(item,empty); if(item!=null){ https://blog.ngopal.com.np/?p=1197&preview=true //----------------------- //I'm making my sexy GUI //----------------------- //Do you stuffs of making your cell sexy //finally every thing is just setup setGraphic(<your gui>); } } }; //this is my chemical solution //Need to call on every cell for making things work cell.init(obj); //Take my cell return cell; } }); |
In above code sample here we have added our own list cell factory so that that cell knows what we want to do on drag events.
I’ve also made one simple app(Friends List) by using this Facility and one of my best control(AutoFillTextBox). I’ve made that simple app available for you to see if you want.
I hope you enjoyed reading this post.
Thanks you ! See you coming free days. Have a good day 🙂
Pingback: Java desktop links of the week, May 14 | Jonathan Giles
Pingback: JavaFX links of the week, May 14 // JavaFX News, Demos and Insight // FX Experience
hi Narayan, your solution looks good. I need to develop something similar for my Table where I should be able to drag and drop the rows. Let me see how it goes in my side.
Hi Sarad,
The algorithm is same on TableView. You just need to know the row index of items ObservableList of any table cell while on DND event and change the indexing of the ‘items’ ObservableList .Finally the effects will be automatically updated in main TableView.
Thanks
Narayan
Thanks , the dragdrop is working for my table. However, I have an issue with a dynamic column getting updated automatically after the drag&drop.
The thing is – user can add columns dynamically in my table. To adjust this , I have a map in the data Model object, I have linked the map with the CellValueFactory.
Now when I drag and drop a row onto another , the newest data on the cell gets overwritten .
The cellvalueFactory is as follows:
newCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures, ObservableValue>() {
@Override
public ObservableValue call(TableColumn.CellDataFeatures p) {
String columnData = “Please enter the data”;
Map agendaMap = p.getValue().getAgendaMap();
if (agendaMap.get(columnName) != null ) {
columnData = (String) agendaMap.get(columnName);
}
System.out.println(“ColumnData: ” + columnData);
return new SimpleStringProperty(columnData);
}
});
I have dynamic column with “”Please enter the data” as text in all the rows. Now I edit one of the row with value “1234”. Then I drag and drop the row on another position , now all the rows have “1234” . I believe there is something wrong with my cellvalueFactory. Please let me know your views…
these kind of post are always inspiring and i prefer to read quality content so i’m happy to find many good point here in the post, writing is simply great, thank you for the posthttp://www.creditocartao.net
Pingback: Simple Drag&Drop-ListView for JavaFX 2.1 | skynet-gfx.de
Pingback: Source Code : Draggable ListCell as FriendList Demo « Java and FX
I get the error when I try to run any ideas?
I am on a MAC using java 1.7.0_05, javafx2.2 beta build 18
AutoFillTextBox is not a valid type.
/Users/David/Desktop/FriendsList/build/classes/friendslist/GUIFX.fxml:23
at javafx.fxml.FXMLLoader.createElement(FXMLLoader.java:2381)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2311)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2131)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2028)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2742)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2721)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2694)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2683)
at friendslist.FriendsList.start(FriendsList.java:37)
at com.sun.javafx.application.LauncherImpl$5.run(LauncherImpl.java:319)
at com.sun.javafx.application.PlatformImpl$5.run(PlatformImpl.java:206)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:173)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)
Hi David,
It’s telling that you are using the AutoFillTextBox control which is not currently available in your GUIFX.fxml containing package. Please make sure that you have the package “np.com.ngopal.autocomplete” which contains the AutoFillTextBox control . Also make sure that you are importing the control inside GUIFX.fxml
like below
< ?import np.com.ngopal.autocomplete.* ?>
Thanks
Fixed, thanks for quick reply.
This is exactly what I was looking for.
reds
Dave
Hi can you please tell me how to do the drag and drop on the split pane
Hi duke,
The concept is same. Save the variable/object in temp when drag operation initialize and work on drag operation stuffs like in this blog post.
Thanks
Hi Narayan can u post an example of drag and drop on the split pane i am unable to code it
Hi Narayan,
Thank you for this useful class. Last week I tried to convert the functionality from ListCell to TableRow, and it worked perfect. Now, I’m trying to implement the ListCellX as you wrote. The ListView seems empty (no Strings on it) but it actually has the clickable elements in each Cell (I know because I print it in the output terminal). Do you have any solution for this view problem?
If you’re using an EMF model you should have a look at the EMF Edit integration for JavaFX provided by e(fx)clipse that allows you to add drag & drop and undo/redo support with almost no additional code. Check this blog post to see it in action: http://tomsondev.bestsolution.at/2012/12/13/emf-edit-support-is-coming-to-javafx-via-efxclipse/
@Ori ,
I think you need to check on the Cell Data emptiness/null before adding the EventListener to the Cell.
Thanks
Narayan
Hi,
could you post the imports used for the class ListCellX please? I cannot get it to work…
Do you mind if I quote a few of your articles as long as I provide credit
and sources back to your weblog? My blog site is in the exact same niche as yours and my visitors would certainly benefit from some of the
information you provide here. Please let me know if
this alright with you. Many thanks!
@birmingham, Yes you can
Hi,
Really nice article. I’ve found one problem though in JavaFX 2.2. The drag ‘n drop implementation behaves differently depending which platform you are using. In Windows, this example works great but when I run it in GNU/Linux it removes (I think) the selected item when you hover over another item in the list. Really strange. I’ve been troubleshooting for days why my application won’t work and then I tried it on windows and it runs without any problem. Really frustrating.
Maybe someone else has experience the same issue?
Hi there, i read your blog occasionally and i own a similar one and i was just wondering if you get a lot of
spam responses? If so how do you reduce it, any
plugin or anything you can suggest? I get so much lately it’s driving me crazy so any help is very much appreciated.
Use the akismet Spam filterer of WordPress
Hi, I alyways get an java.lang.IllegalArgumentException: failed to parse:mycell Exception. Don’t know what is wrong..
Hi Alex,
I have added Git repo for this which you can directly get source from here:
https://blog.ngopal.com.np/2012/07/16/source-code-draggable-listcell-as-friends-list-demo
FYI: I have tested in my jfx version 2.2.5
Thanks
Narayan
Hi,
Thank you so much for posting your solution. It was very helpful!
Hi,
Your job look’s great. But I downloaded the source and I can’t import it, my ecplise doesn’t considere your code as a project. If I create a new project and I copy the sources, I have many errors (SkinBase not found, constructor BehaviorBase undefined…). Do you have any Idea why it doesn’t work ?
Did you try out in netbeans as this project is based on the Netbeans.
Ok I that’s why it doesn’t work ^^. So, I’ll try it on netbeans. Thx
Hello thanks for sharing your code that’s awesome!
However I encounter a problem, whenever I drag an item form my list it gets duplicated. In other words the list expands. I still have not found where the bug is in your code.
Kind regards,
Xela 🙂
I will do some check and let you know.
Hi, Narayan —
I’ve implemented your code, and it’s mostly working….
I have one problem:
If I have a list with 3 items, and move the 1st item to the 2nd position, The 1st and 2nd item display correctly, but the 3rd item does NOT show up.
I’ve looked through the code (in the setOnDragEntered event handler), and the items list looks correct; it just seems like the last item is not displayed. (If you move an item to the last position, then all items will appear again.)
Have you noticed this issue?
Hi there,
I implemented your code in my project as well, but the listView doesn’t show the text. So the items are there and I can drag and drop them but the text content is not visible…