Java在列表中拖放图像
Posted
技术标签:
【中文标题】Java在列表中拖放图像【英文标题】:Java drag and drop images in a list 【发布时间】:2011-11-05 14:00:47 【问题描述】:我正在寻找一种方法来以水平顺序显示一系列图片(带有图像的 JPanel,可能还有其他一些小组件)。
用户应该能够通过拖放重新排列图像的顺序。 我该怎么做呢?带有一些自定义组件和 D&D 的 JList 是要走的路吗? 一些需要考虑的问题(我听说让组件具有相同的尺寸会提高性能)。
【问题讨论】:
【参考方案1】:以下示例向您展示如何在列表中水平显示图像并使用拖放重新排列它们。如果空间不足,列表将水平换行。
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.io.Serializable;
public class ImagePreviewListTest
public static void main(String[] args) throws Exception
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
JFrame frame = new JFrame("Image panel");
frame.setSize(800, 300);
frame.setLocationByPlatform(true);
JList imageList = createImageList();
frame.getContentPane().add(new JScrollPane(imageList));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
private static JList createImageList()
JList imageList = new JList(createModel());
imageList.setCellRenderer(new ImageCellRenderer());
imageList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
imageList.setVisibleRowCount(-1);
imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
imageList.setFixedCellWidth(240);
imageList.setFixedCellHeight(120);
imageList.setDragEnabled(true);
imageList.setDropMode(DropMode.INSERT);
imageList.setTransferHandler(new ImageTransferHandler(imageList));
return imageList;
private static DefaultListModel createModel()
DefaultListModel model = new DefaultListModel();
model.addElement(new ColorIcon(Color.RED));
model.addElement(new ColorIcon(Color.GREEN));
model.addElement(new ColorIcon(Color.BLACK));
model.addElement(new ColorIcon(Color.BLUE));
model.addElement(new ColorIcon(Color.MAGENTA));
model.addElement(new ColorIcon(Color.PINK));
model.addElement(new ColorIcon(Color.YELLOW));
model.addElement(new ColorIcon(Color.ORANGE));
return model;
static class ImageTransferHandler extends TransferHandler
private static final DataFlavor DATA_FLAVOUR = new DataFlavor(ColorIcon.class, "Images");
private final JList previewList;
private boolean inDrag;
ImageTransferHandler(JList previewList)
this.previewList = previewList;
public int getSourceActions(JComponent c)
return TransferHandler.MOVE;
protected Transferable createTransferable(JComponent c)
inDrag = true;
return new Transferable()
public DataFlavor[] getTransferDataFlavors()
return new DataFlavor[] DATA_FLAVOUR;
public boolean isDataFlavorSupported(DataFlavor flavor)
return flavor.equals(DATA_FLAVOUR);
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException
return previewList.getSelectedValue();
;
public boolean canImport(TransferSupport support)
if (!inDrag || !support.isDataFlavorSupported(DATA_FLAVOUR))
return false;
JList.DropLocation dl = (JList.DropLocation)support.getDropLocation();
if (dl.getIndex() == -1)
return false;
else
return true;
public boolean importData(TransferSupport support)
if (!canImport(support))
return false;
Transferable transferable = support.getTransferable();
try
Object draggedImage = transferable.getTransferData(DATA_FLAVOUR);
JList.DropLocation dl = (JList.DropLocation)support.getDropLocation();
DefaultListModel model = (DefaultListModel)previewList.getModel();
int dropIndex = dl.getIndex();
if (model.indexOf(draggedImage) < dropIndex)
dropIndex--;
model.removeElement(draggedImage);
model.add(dropIndex, draggedImage);
return true;
catch (Exception e)
e.printStackTrace();
return false;
protected void exportDone(JComponent source, Transferable data, int action)
super.exportDone(source, data, action);
inDrag = false;
static class ImageCellRenderer extends JPanel implements ListCellRenderer
DefaultListCellRenderer defaultListCellRenderer = new DefaultListCellRenderer();
JLabel imageLabel = new JLabel();
JLabel descriptionLabel = new JLabel();
ImageCellRenderer()
setLayout(new BorderLayout());
Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
imageLabel.setBorder(emptyBorder);
descriptionLabel.setBorder(emptyBorder);
add(imageLabel, BorderLayout.CENTER);
add(descriptionLabel, BorderLayout.SOUTH);
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
defaultListCellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
setBorder(defaultListCellRenderer.getBorder());
setBackground(defaultListCellRenderer.getBackground());
imageLabel.setIcon((Icon)value);
descriptionLabel.setText("Description");
return this;
static class ColorIcon implements Icon, Serializable
private Color color;
ColorIcon(Color color)
this.color = color;
public void paintIcon(Component c, Graphics g, int x, int y)
g.setColor(color);
g.fillRect(x, y, getIconWidth(), getIconHeight());
public int getIconWidth()
return 200;
public int getIconHeight()
return 100;
public boolean equals(Object o)
if (o == null || getClass() != o.getClass())
return false;
return color.equals(((ColorIcon)o).color);
【讨论】:
【参考方案2】:Drag&Drop for Images?
【讨论】:
【参考方案3】:创建一个包含图像的 ListModel。
创建一个显示它们的 ListCellRenderer 并将其设置为 List 的渲染器。您可以在渲染器中使用 JLabel,以便轻松设置图像。
创建一个知道如何处理 DataFlavor.imageFlavor 的 TransferHandler。 StanislavL 引用的例子是一个开始。
设置列表的 transferHandler 属性。
【讨论】:
以上是关于Java在列表中拖放图像的主要内容,如果未能解决你的问题,请参考以下文章