Swing/DnDReorderList のバックアップの現在との差分(No.1)
TITLE:TransferHandlerを使ったJListのドラック&ドロップによる並べ替え
TransferHandlerを使ったJListのドラック&ドロップによる並べ替え
Posted by terai at 2008-09-29- category: swing folder: DnDReorderList title: TransferHandlerを使ったJListのドラッグ&ドロップによる並べ替え tags: [JList, TransferHandler, DragAndDrop] author: aterai pubdate: 2008-09-29T13:33:14+09:00 description: JListのアイテムを複数選択し、ドラッグ&ドロップで並べ替えを可能にするTransferHandlerを作成します。 image:
概要
JList
のアイテムを複数選択し、ドラッグ&ドロップで並べ替えを可能にするTransferHandler
を作成します。
Screenshot
Advertisement
概要
JListのアイテムを複数選択し、ドラック&ドロップで並べ替えを可能にするTransferHandlerを作成します。サンプルコード
#spanend
#spanadd
class ListItemTransferHandler extends TransferHandler {
#spanend
protected final DataFlavor localObjectFlavor;
protected int[] indices;
protected int addIndex = -1; // Location where items were added
protected int addCount; // Number of items added.
-&jnlp;
-&jar;
-&zip;
protected ListItemTransferHandler() {
super();
localObjectFlavor = new DataFlavor(List.class, "List of items");
}
#spandel
#screenshot
#spanend
@Override protected Transferable createTransferable(JComponent c) {
JList<?> source = (JList<?>) c;
indices = source.getSelectedIndices();
List<?> transferredObjects = source.getSelectedValuesList();
return new Transferable() {
@Override public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] {localObjectFlavor};
}
#spandel
**サンプルコード [#p71d9322]
#spanend
#spandel
#code{{
#spanend
#spandel
class ListItemTransferHandler extends TransferHandler {
#spanend
private final DataFlavor localObjectFlavor;
private Object[] transferedObjects = null;
public ListItemTransferHandler() {
localObjectFlavor = new ActivationDataFlavor(Object[].class, DataFlavor.javaJVMLocalObjectMimeType, "Array of items");
@Override public boolean isDataFlavorSupported(DataFlavor flavor) {
return Objects.equals(localObjectFlavor, flavor);
}
#spanadd
#spanend
@Override public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (isDataFlavorSupported(flavor)) {
return transferredObjects;
} else {
throw new UnsupportedFlavorException(flavor);
}
}
};
}
@Override
protected Transferable createTransferable(JComponent c) {
JList list = (JList) c;
indices = list.getSelectedIndices();
transferedObjects = list.getSelectedValues();
return new DataHandler(transferedObjects, localObjectFlavor.getMimeType());
#spanadd
#spanend
@Override public boolean canImport(TransferSupport info) {
return info.isDrop() && info.isDataFlavorSupported(localObjectFlavor);
}
@Override
public boolean canImport(TransferHandler.TransferSupport info) {
if (!info.isDrop() || !info.isDataFlavorSupported(localObjectFlavor)) {
return false;
}
return true;
#spanadd
#spanend
@Override public int getSourceActions(JComponent c) {
return TransferHandler.MOVE; // TransferHandler.COPY_OR_MOVE;
}
@Override
public int getSourceActions(JComponent c) {
return TransferHandler.COPY_OR_MOVE;
}
@Override
public boolean importData(TransferHandler.TransferSupport info) {
if (!canImport(info)) {
#spanadd
#spanend
@SuppressWarnings("unchecked")
@Override public boolean importData(TransferHandler.TransferSupport info) {
TransferHandler.DropLocation tdl = info.getDropLocation();
if (!(tdl instanceof JList.DropLocation)) {
return false;
}
JList target = (JList)info.getComponent();
JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
DefaultListModel listModel = (DefaultListModel)target.getModel();
JList.DropLocation dl = (JList.DropLocation) tdl;
JList<?> target = (JList<?>) info.getComponent();
DefaultListModel listModel = (DefaultListModel) target.getModel();
// boolean insert = dl.isInsert();
int max = listModel.getSize();
int index = dl.getIndex();
//boolean insert = dl.isInsert();
int max = listModel.getSize();
if(index<0 || index>max) {
index = max;
}
// If it is out of range, it is appended to the end
index = index < 0 ? max : index;
index = Math.min(index, max);
addIndex = index;
#spandel
#spanend
// ???
//if (indices != null && index >= indices[0] - 1 && index <= indices[indices.length - 1]) {
// indices = null;
// return false;
//}
#spandel
#spanend
try {
Object[] values = (Object[])info.getTransferable().getTransferData(localObjectFlavor);
addCount = values.length;
for(int i=0;i<values.length;i++) {
int idx = index++;
listModel.add(idx, values[i]);
target.addSelectionInterval(idx, idx);
List<?> values = (List<?>) info.getTransferable()
.getTransferData(localObjectFlavor);
for (Object o : values) {
int i = index++;
listModel.add(i, o);
target.addSelectionInterval(i, i);
}
addCount = values.size();
return true;
}catch(UnsupportedFlavorException ufe) {
ufe.printStackTrace();
}catch(java.io.IOException ioe) {
ioe.printStackTrace();
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
return false;
}
@Override
protected void exportDone(JComponent c, Transferable data, int action) {
#spanadd
#spanend
@Override protected void exportDone(
JComponent c, Transferable data, int action) {
cleanup(c, action == TransferHandler.MOVE);
}
#spanadd
#spanend
private void cleanup(JComponent c, boolean remove) {
if(remove && indices != null) {
JList source = (JList)c;
DefaultListModel model = (DefaultListModel)source.getModel();
//If we are moving items around in the same list, we
//need to adjust the indices accordingly, since those
//after the insertion point have moved.
if(addCount > 0) {
for(int i=0;i<indices.length;i++) {
if(indices[i]>addIndex) {
if (remove && Objects.nonNull(indices)) {
// If we are moving items around in the same list, we
// need to adjust the indices accordingly, since those
// after the insertion point have moved.
if (addCount > 0) {
for (int i = 0; i < indices.length; i++) {
if (indices[i] >= addIndex) {
indices[i] += addCount;
}
}
}
for(int i=indices.length-1;i>=0;i--) {
JList<?> source = (JList<?>) c;
DefaultListModel model = (DefaultListModel) source.getModel();
for (int i = indices.length - 1; i >= 0; i--) {
model.remove(indices[i]);
}
}
indices = null;
indices = null;
addCount = 0;
addIndex = -1;
}
private int[] indices = null;
private int addIndex = -1; //Location where items were added
private int addCount = 0; //Number of items added.
}
View in GitHub: Java, Kotlin解説
上記のサンプルは、Demo - BasicDnD (Drag and Drop and Data Transfer)、Drag and drop for non-String objectsを参考にしてTransferHandlerを作成し、以下のようにJListに設定しています。解説
上記のサンプルのTransferHandler
は、主にDrag and Drop and Data Transfer: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)のListTransferHandler.javaを参考にして作成しています。ただし、このListTransferHandler.java
は項目を複数選択して、JList
内での並べ替えは想定していない(もしくはバグ?)ようなので、importData(...)
メソッドや、cleanup()
メソッドを修正しています。
JList list = new JList(listModel);
list.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.setTransferHandler(new ListItemTransferHandler());
list.setDropMode(DropMode.INSERT);
list.setDragEnabled(true);
-
importData
- 使用されていない?
importString(...)
の内容をこちらに移動
- 使用されていない?
-
cleanup
- 例えば、項目
0, 1, 2
を複数選択して1
と2
の間にドロップすると1, 2, 2
になる(0
が消えて2
になる)ので、以下のように修正#spanend #spanadd for (int i = 0; i < indices.length; i++) { #spanend // if (indices[i] > addIndex) { if (indices[i] >= addIndex) { // ... #spanadd
- 例えば、項目
JListの項目をドラッグ&ドロップとは異なり、複数アイテムを選択してDrag&Dropによる移動が可能になっています。 JListの項目をドラッグ&ドロップとは異なり、複数アイテムを選択して
Drag&Drop
による移動が可能になっています。
参考リンク
- Demo - BasicDnD (Drag and Drop and Data Transfer)
- Drag and drop for non-String objects
- JListの項目をドラッグ&ドロップ
参考リンク
- Drag and Drop and Data Transfer: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)
- JListの項目をドラッグ&ドロップ
- JListのアイテムをラバーバンドで複数選択、ドラッグ&ドロップで並べ替え