Drag-and-drop to order items in Swing - java

I have a list of items to display in Swing. For simplicity, imagine that each item consists of only a name. I want the user to be able to order these items by dragging and dropping them above/below each other. What's the best way to achieve this?
Alternatively, could this perhaps be accomplished in using a JList, with an "up" and "down" button that would move the selected item up/down in the list. This would require updating the graphical display instantly on each click (I don't know how to do this), and saving the new order by getting the items in the list in their current order (which I also don't know how to do).
Or might a drag-and-drop solution be more feasible?

It'd probably be easier to implement this with the JList solution you mention, so I'll give you some pointers on that (I'm not very experienced with D&D).
Basically, you want to have three components: a JList and two (one up, one down) JButtons. You'll also probably want a custom list model. If you're unfamiliar with models or list models, check out this tutorial. Otherwise, read on.
In the list model class (e.g., ReorderableListModel), go ahead and define two methods: public void moveUp(int index) and public void moveDown(int index).
The code for moveUp is as follows:
if (index > 0) { // error checking
// Swap the given index with the previous index.
// (where `list` is the name of your list variable)
Collections.swap(list, index, index - 1);
}
// Finally, notify the `JList` that the list structure has changed.
fireContentsChanged(this, index - 1, index);
moveDown is similar:
if (index < getSize() - 1) {
Collections.swap(list, index, index + 1);
}
fireContentsChanged(this, index, index + 1);
Now, we need to implement the action listeners for the buttons. For the up button, go try this listener code:
// First, move the item up in the list.
listModel.moveUp(list.getSelectedIndex());
// Now, set the selection index to keep the same item selected.
//
// If you use the default list selection interval, setting the index to -1
// will do nothing (so it's okay, we don't need error checking here).
list.setSelectedIndex(list.getSelectedIndex() - 1);
Add a similar "move down" method and you're done!
With respect to "updating the graphical display instantly on each click," that's what the fireContentsChanged method in the model class does. JList will do the updating for you.

It is a functionality hard to achieve using just swing. Have you heard about JavaFX? It is a great graphic framework to work with if you want to achieve more dynamic functionality in desktop applications, take a look to this article: http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html
Here you will be able to find links with more information, as well as some examples. Best regards.

Related

Showing a counter dynamically for JList items highlighted

I have a program that I created for work. This program takes an uploaded file, reads it, and puts the data into a JList in the GUI. The GUI actually has two lists and the user is able to move items between the left and right list by highlighting them like usual with a JList and then hitting an arrow to move the items. The lists are multiple-interval selection.
One small addition I would like to add is some type of counter that shows the user how many items they have selected before they actually move them between lists. This would need to be dynamic so if the user holds control down and begins clicking the counter will continue to update the number of highlighted items.
As the lists are often quite large and a user might need to move an odd number of transactions between the lists (Think 300 transactions in left list and the user needs to move exactly 50) it would be beneficial to have this counter.
Can anyone think of how this could be done? I'm not sure how to add an action listener to just clicking on the items. Please also let me know if I need to elaborate any more.
Generally my question is can I create an action listener just for when a user clicks a item in a JList that updates a counter for the current selected indices? Also it would need to change when they no longer have selected an indice.
Register a ListSelectionListener with your JList.
The listener could simply query how many rows are selected and update the number in the panel to that. Perhaps use getSelectedValues().size().
http://docs.oracle.com/javase/8/docs/api/javax/swing/JList.html#addListSelectionListener-javax.swing.event.ListSelectionListener-

Object to ArrayList to JList and back again (A few questions)

Program Outline:
I plan to make a simple Java program that will load Vehicle objects (Vehicle being the superclass, EnginedVehicle and GoodsVehicle being the subclasses) from an XML file into an ArrayList which will then be displayed on a JList. The user will be able to show/hide the different Vehicle types using check boxes, add a new vehicle type or press the selected item in the JList and edit or delete it. The program will then put the Objects back into the ArrayList where it can be then saved back to the XML file.
Question: So, I am completely fine with the loading of the XML file into the ArrayList and putting that object onto the JList but the thing that is hurting my head is thinking about how I am going to:
What is the best way of getting the object back from the JList ready for it to be modified or deleted and put back into the ArrayList?
How would I show/hide the different types of Vehicles in the JList using the check boxes?
I understand this may seem a lot but, this is my first post and I am new to the community and I have fairly good knowledge of Java and OOP programming but I have just finished writing a fairly big website and going back to Java is a headache.
Since your ArrayList should be equal in size (item count) to your JList, your JList will have the index you're interested based on selection. Regardless if you want to modify or delete the item, store what index it was at and remove the item from the JList (You should be using a DefaultListModel). Use this index value to get the object from your ArrayList. If you're modifying, modify your object as needed, you shouldn't have to remove the object from the ArrayList for modifications, and place it back into your DefaultListModel. If it's a delete, then just remove the object from your ArrayList using the index value you stored.
As far as displaying (show/hide), clear your DefaultListModel (which will clear your JList), iterate through your ArrayList and add the items to the DefaultListModel that match your checkbox selection criteria.
EDIT:
I didn't take into consideration of possibly modifying/deleting items when items are hidden. For this, may want your objects to have a field that stores what index they are at in the ArrayList. This way when you do your filter, I would copy the items from your "Master" ArrayList into a sub list that you can populate your DefaultListModel. Then you apply the same logic to this sublist when selecting an item from you JList, then take your changes from your sublist and apply them to the "Master" ArrayList.
Keep in mind that when you remove an item, you'll have to reassign all items index location from that point on down.
I'm sure there is probably a cleaner way of doing this, but this is what first comes to mind for me.
I don't know if I'm horribly mistaken, but why change to a JList at all? Do you use your JList as a parameter to visualize the information in it? If yes, why dont you use your ArrayList instead? Then the checkboxes only change the visibility ot the Items of the List. So you dont have to care about indices, because they stay the same. And new entries, can be made as well... maybe im wrong but i guess you got kind of a GUI for the user to browse/alter/add new vehicles?

I'm adding an empty row to my JTable (implementing AbstractTableModel). How do I update my model in real time?

Ok so I think the title is all I've got to ask here.
My AbstractTableModel works fine, when I want to add an empty row, I use the following code to do so:
public void addRow() {
Object[][] oldData = data;
data = new Object[oldData.length + 1][3];
// Copy old data to new data
for (int x = 0; x < oldData.length; x++) {
data[x] = oldData[x];
}
// Append new row
data[oldData.length] = new Object[] {"", "", false};
fireTableRowsInserted(data.length - 2, data.length - 1);
}
Now, since I'm showing an empty row, I want the user to edit it, and I assume that the user will. Now, how do I make sure that the data is saved in my array as the user makes changes? Or, if that's not possible, what better alternative is there?
Ok so I should probably explain what I want to do:
I'm loading contents from a file, and displaying as a table. Now, the user might add new rows to the table on clicking the Add Row button. This will add 1 empty row per click. (In this image above is an instance when the button is pressed twice.
Now, I want that the user can edit the cells, and then maybe delete some rows (maybe) but on clicking the Save Database button, the updated data in the table is stores.
You may get a better understanding by comparing several approaches:
In this example, either a background thread or a button can add a new row to a table. The background thread sequences instances of Runnable on the EDT via invokeLater(). It is conceptually easier to understand, but it is also easier to get wrong.
SwingWorker encapsulates sequencing access to shared data. The API and tutorial show the basic approach of updating a component's model using publish()/process(). This preferred mechanism is more robust and scalable.
In this more advanced example, a Swing Timer paces an Executor that controls a series of SwingWorker instances.
In all cases, the tables remain functional. You might use any as a basis for an sscce.
Addendum: Could you explain a little more about the strategies you suggested?
I've updated the list of examples and suggested some things to look for in context.

Java ZK ListBox listModel out of sync after sorting

hey guys i am new to ZK framework i have a listbox being sorted in the view later i pass the listBox to the controller and i need the items being selected by the user but in the model the items are syncronized with the sorting but in the getSelection array is not syncronized with the sort insted with the original data here is the code.
public void createPDFFromModel(Listbox list,String ref){
BindingListModelList model = (BindingListModelList)list.getModel();
for(int i=0;i<model.size();i++){
System.out.println((((ZamoraListitemAdapter)model.get(i)).getName()));
}
System.out.println("-------------------------------------------");
//Data Printed OK.
java.util.ArrayList<ZamoraListitemAdapter>selections = new java.util.ArrayList<ZamoraListitemAdapter>(model.getSelection());
for(int i=0;i<selections.size();i++){
ZamoraListitemAdapter clazz = (ZamoraListitemAdapter)selections.get(i);
System.out.println(clazz.getName());
//Out of sync with model and with sorting
}
my question is how i get the order of the items after the sort in getSelection model. i am using ZK 5.2.8
You could sort selections after you create it.
There are maybe other/better solutions, but you have
to write what you try to achieveif you need more help.
Reply to Comment
What I mean is
ArrayList<ZamoraListitemAdapter>selections =
new ArrayList<ZamoraListitemAdapter>(model.getSelection());
Collections.sort(selections);
So selections is a List of all your selected items and as long
as you compare the items the same way, they should be in the right order
In case you mean reorder and not sorting...
For me sorting means it is automatic and done by a algorithm.
Reordering instead means you, for example, drag the objects around.
If you mean reordering, and your Model hasn't a way to know if
a item is selected, you probably did something wrong.
Cos zk has got the two classes ListModelList and AbstractListModel
wich implement all methods needed for selection behavior and a custom
Model should, if the programmer wants a selectable Model, inherent
from one of them, cos it's the easiest way.
You should may also read this.
model.getSelection()
returns a Set (no order), instead use
model.getInnerList()
that returns ListModeList

Multi-leveled (nested?) Jlist in Java

Is there a way to create a JList that has more than one (I'm aiming at three) levels?
Something like this:
level 1 item
level 2 item
level 2 item
level 3 item
level 1 item
level 1 item
level 2 item
level 2 item
level 3 item
level 3 item
I have (up to)three-level-component GUI in my program, and I would need to somehow enable user to organise the elements of the GUI, to move them above or under each other.
Can it be done with JList, or is there another way of dealing with such things?
Maybe some library?
I think you could, yes, but you're in for a world of hurt that way. JList naturally represents a List from a conceptual point of view, not a tree, meaning most of the ordering logic would have to be done by you. What you're probably interested in is a JTree instead.
I think you should use JTree for that.
You can implement your own ListCellRenderer and your own ListModel.
http://docs.oracle.com/javase/6/docs/api/javax/swing/JList.html

Categories