問題描述
我遇到了一個(gè)關(guān)于使用拖放對(duì) JList 中的元素進(jìn)行重新排序的問題.以下代碼是對(duì)代碼的修改,您可以在其中將元素從一個(gè) JList 拖到另一個(gè)(僅以一種方式工作).我試圖讓它只對(duì)一個(gè) JList 可用,但元素甚至不能被拖出列表.所以我想它不能這樣做.任何想法我做錯(cuò)了什么或沒有考慮到?
I encountered a problem regarding reordering elements in a JList using Drag and Drop. This following code is a modification of a code where you could drag elements from one JList to another (worked only one way). I tried to make it usable for only one JList, but the elements can't even be dragged out of the list. So I guess it can't be done this way. Any ideas what I'm doing wrong or not taking into consideration?
這個(gè)想法是讓它為帶有縮略圖的 Jlist 工作,但因?yàn)槲沂仓敛荒茏屗挥米址ぷ?.....我一直在研究幾個(gè) D'n'D 教程,但我仍然無法讓它工作.任何幫助表示贊賞.
The idea is to get it to work for a Jlist with thumbnails, but since I can't even get it to work with just strings... I have been looking into several D'n'D tutorials, but still I can't get it to work. Any help is appreciated.
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.io.IOException;
public class DragAndDrop extends JFrame {
DefaultListModel<String> transport = new DefaultListModel<String>();
JList<String> transportList = new JList<String>(transport);
public DragAndDrop() {
setLayout(new FlowLayout());
transport.addElement("Bike");
transport.addElement("Car");
transport.addElement("Truck");
transport.addElement("Boat");
JScrollPane transportScroll = new JScrollPane(transportList);
transportScroll.setBorder(new TitledBorder("Transportation"));
add(transportScroll);
transportList.setDragEnabled(true);
transportList.setTransferHandler(new TransferHandler() {
int index;
@Override
public int getSourceActions(JComponent comp) {
return COPY_OR_MOVE;
}
@Override
public Transferable createTransferable(JComponent comp) {
index = transportList.getSelectedIndex();
return new StringSelection(transportList.getSelectedValue());
}
@Override
public void exportDone( JComponent comp, Transferable trans, int action ) {
if (action==MOVE) {
transport.remove(index);
}
}
});
transportList.setDropMode(DropMode.ON);
transportList.setTransferHandler(new TransferHandler() {
@Override
public boolean canImport(TransferHandler.TransferSupport support) {
// data of type string?
return support.isDataFlavorSupported(DataFlavor.stringFlavor);
}
@Override
public boolean importData(TransferHandler.TransferSupport support) {
try {
// convert data to string
String s = (String)support.getTransferable().getTransferData(DataFlavor.stringFlavor);
JList.DropLocation dl = (JList.DropLocation)support.getDropLocation();
transport.add(dl.getIndex(),s);
return true;
}
catch (UnsupportedFlavorException e) {}
catch (IOException e) {}
return false;
}
});
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new DragAndDrop();
}
}
PS.抱歉,如果這是一個(gè)重新發(fā)布.
PS. Sorry if this turns out to be a re-post.
編輯我想我已經(jīng)解決了:必須使用不同的 transferHandlers - 應(yīng)該只有一個(gè)包含第二個(gè)中的所有方法.
EDIT I think I got it fixed: had to different transferHandlers - should only have one with all the methods from the second one as well.
推薦答案
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DragSource;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Objects;
// import javax.activation.ActivationDataFlavor;
// import javax.activation.DataHandler;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
public class DragAndDropTest {
public JComponent makeUI() {
DefaultListModel<Thumbnail> m = new DefaultListModel<>();
for (String s : Arrays.asList("error", "information", "question", "warning")) {
m.addElement(new Thumbnail(s));
}
JList<Thumbnail> list = new JList<>(m);
list.getSelectionModel().setSelectionMode(
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.setTransferHandler(new ListItemTransferHandler());
list.setDropMode(DropMode.INSERT);
list.setDragEnabled(true);
// https://java-swing-tips.blogspot.com/2008/10/rubber-band-selection-drag-and-drop.html
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(0);
list.setFixedCellWidth(80);
list.setFixedCellHeight(80);
list.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
list.setCellRenderer(new ListCellRenderer<Thumbnail>() {
private final JPanel p = new JPanel(new BorderLayout());
private final JLabel icon = new JLabel((Icon)null, JLabel.CENTER);
private final JLabel label = new JLabel("", JLabel.CENTER);
@Override
public Component getListCellRendererComponent(
JList<? extends Thumbnail> list, Thumbnail value, int index,
boolean isSelected, boolean cellHasFocus) {
icon.setIcon(value.icon);
label.setText(value.name);
label.setForeground(isSelected ? list.getSelectionForeground()
: list.getForeground());
p.add(icon);
p.add(label, BorderLayout.SOUTH);
p.setBackground(isSelected ? list.getSelectionBackground()
: list.getBackground());
return p;
}
});
return new JScrollPane(list);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> createAndShowGUI());
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new DragAndDropTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class Thumbnail implements Serializable {
public final String name;
public final Icon icon;
public Thumbnail(String name) {
this.name = name;
this.icon = UIManager.getIcon("OptionPane." + name + "Icon");
}
}
// @camickr already suggested above.
// https://docs.oracle.com/javase/tutorial/uiswing/dnd/dropmodedemo.html
@SuppressWarnings("serial")
class ListItemTransferHandler extends TransferHandler {
protected final DataFlavor localObjectFlavor;
protected int[] indices;
protected int addIndex = -1; // Location where items were added
protected int addCount; // Number of items added.
public ListItemTransferHandler() {
super();
// localObjectFlavor = new ActivationDataFlavor(
// Object[].class, DataFlavor.javaJVMLocalObjectMimeType, "Array of items");
localObjectFlavor = new DataFlavor(Object[].class, "Array of items");
}
@Override
protected Transferable createTransferable(JComponent c) {
JList<?> source = (JList<?>) c;
c.getRootPane().getGlassPane().setVisible(true);
indices = source.getSelectedIndices();
Object[] transferedObjects = source.getSelectedValuesList().toArray(new Object[0]);
// return new DataHandler(transferedObjects, localObjectFlavor.getMimeType());
return new Transferable() {
@Override public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] {localObjectFlavor};
}
@Override public boolean isDataFlavorSupported(DataFlavor flavor) {
return Objects.equals(localObjectFlavor, flavor);
}
@Override public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (isDataFlavorSupported(flavor)) {
return transferedObjects;
} else {
throw new UnsupportedFlavorException(flavor);
}
}
};
}
@Override
public boolean canImport(TransferSupport info) {
return info.isDrop() && info.isDataFlavorSupported(localObjectFlavor);
}
@Override
public int getSourceActions(JComponent c) {
Component glassPane = c.getRootPane().getGlassPane();
glassPane.setCursor(DragSource.DefaultMoveDrop);
return MOVE; // COPY_OR_MOVE;
}
@SuppressWarnings("unchecked")
@Override
public boolean importData(TransferSupport info) {
TransferHandler.DropLocation tdl = info.getDropLocation();
if (!canImport(info) || !(tdl instanceof JList.DropLocation)) {
return false;
}
JList.DropLocation dl = (JList.DropLocation) tdl;
JList target = (JList) info.getComponent();
DefaultListModel listModel = (DefaultListModel) target.getModel();
int max = listModel.getSize();
int index = dl.getIndex();
index = index < 0 ? max : index; // If it is out of range, it is appended to the end
index = Math.min(index, max);
addIndex = index;
try {
Object[] values = (Object[]) info.getTransferable().getTransferData(localObjectFlavor);
for (int i = 0; i < values.length; i++) {
int idx = index++;
listModel.add(idx, values[i]);
target.addSelectionInterval(idx, idx);
}
addCount = values.length;
return true;
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
return false;
}
@Override
protected void exportDone(JComponent c, Transferable data, int action) {
c.getRootPane().getGlassPane().setVisible(false);
cleanup(c, action == MOVE);
}
private void cleanup(JComponent c, boolean remove) {
if (remove && Objects.nonNull(indices)) {
if (addCount > 0) {
// https://github.com/aterai/java-swing-tips/blob/master/DragSelectDropReordering/src/java/example/MainPanel.java
for (int i = 0; i < indices.length; i++) {
if (indices[i] >= addIndex) {
indices[i] += addCount;
}
}
}
JList source = (JList) c;
DefaultListModel model = (DefaultListModel) source.getModel();
for (int i = indices.length - 1; i >= 0; i--) {
model.remove(indices[i]);
}
}
indices = null;
addCount = 0;
addIndex = -1;
}
}
這篇關(guān)于使用拖放重新排序 JList的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!