JAVA:使用DND重新排序的缩略图视图

JAVA:使用DND重新排序的缩略图视图,java,swing,thumbnails,drag-and-drop,Java,Swing,Thumbnails,Drag And Drop,我有一个缩略图查看器的应用程序,它需要显示缩略图,并具有重新排序的功能(使用DnD) 缩略图是一个自定义组件(JLayeredPane) 下面是应用程序的线框,以获得更好的想法 任何要实现的方向/指针或任何可以执行重新排序功能的现有组件都将是一个很大的帮助 我可以将JList与每个元素一起用作缩略图吗 注意:我不希望看到这里的代码。我基本上是从网上偷来的,并稍微修改了一下 import java.awt.BorderLayout; import java.awt.Dimension; impo

我有一个缩略图查看器的应用程序,它需要显示缩略图,并具有重新排序的功能(使用DnD)

缩略图是一个自定义组件(JLayeredPane)

下面是应用程序的线框,以获得更好的想法

任何要实现的方向/指针或任何可以执行重新排序功能的现有组件都将是一个很大的帮助

我可以将JList与每个元素一起用作缩略图吗


注意:我不希望看到这里的代码。

我基本上是从网上偷来的,并稍微修改了一下

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;

public class TestListReorder extends JPanel {

    ArrayListTransferHandler arrayListHandler;

    public TestListReorder() {
        arrayListHandler = new ArrayListTransferHandler();
        JList list1, list2;

        DefaultListModel list1Model = new DefaultListModel();
        list1Model.addElement("0 (list 1)");
        list1Model.addElement("1 (list 1)");
        list1Model.addElement("2 (list 1)");
        list1Model.addElement("3 (list 1)");
        list1Model.addElement("4 (list 1)");
        list1Model.addElement("5 (list 1)");
        list1Model.addElement("6 (list 1)");
        list1 = new JList(list1Model);
        list1.setDropMode(DropMode.USE_SELECTION);
        list1.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        list1.setTransferHandler(arrayListHandler);
        list1.setDragEnabled(true);
        JScrollPane list1View = new JScrollPane(list1);
        list1View.setPreferredSize(new Dimension(200, 100));
        JPanel panel1 = new JPanel();
        panel1.setLayout(new BorderLayout());
        panel1.add(list1View, BorderLayout.CENTER);
        panel1.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        setLayout(new BorderLayout());
        add(panel1, BorderLayout.LINE_START);
        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
    }

    /**
     * Create the GUI and show it. For thread safety, this method should be
     * invoked from the event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        JFrame frame = new JFrame("DragListDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        TestListReorder demo = new TestListReorder();
        frame.setContentPane(demo);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

/*
 * ArrayListTransferHandler.java is used by the 1.4 DragListDemo.java example.
 */
class ArrayListTransferHandler extends TransferHandler {

    DataFlavor localArrayListFlavor, serialArrayListFlavor;
    String localArrayListType = DataFlavor.javaJVMLocalObjectMimeType
            + ";class=java.util.ArrayList";
    JList source = null;
    int[] indices = null;
    int addIndex = -1; //Location where items were added
    int addCount = 0; //Number of items added

    public ArrayListTransferHandler() {
        try {
            localArrayListFlavor = new DataFlavor(localArrayListType);
        } catch (ClassNotFoundException e) {
            System.out
                    .println("ArrayListTransferHandler: unable to create data flavor");
        }
        serialArrayListFlavor = new DataFlavor(ArrayList.class, "ArrayList");
    }

    public boolean importData(JComponent c, Transferable t) {
        JList target = null;
        ArrayList alist = null;
        if (!canImport(c, t.getTransferDataFlavors())) {
            return false;
        }
        try {
            target = (JList) c;
            if (hasLocalArrayListFlavor(t.getTransferDataFlavors())) {
                alist = (ArrayList) t.getTransferData(localArrayListFlavor);
            } else if (hasSerialArrayListFlavor(t.getTransferDataFlavors())) {
                alist = (ArrayList) t.getTransferData(serialArrayListFlavor);
            } else {
                return false;
            }
        } catch (UnsupportedFlavorException ufe) {
            System.out.println("importData: unsupported data flavor");
            return false;
        } catch (IOException ioe) {
            System.out.println("importData: I/O exception");
            return false;
        }

        //At this point we use the same code to retrieve the data
        //locally or serially.

        //We'll drop at the current selected index.
        int index = target.getSelectedIndex();

        //Prevent the user from dropping data back on itself.
        //For example, if the user is moving items #4,#5,#6 and #7 and
        //attempts to insert the items after item #5, this would
        //be problematic when removing the original items.
        //This is interpreted as dropping the same data on itself
        //and has no effect.
        if (source.equals(target)) {
            if (indices != null && index >= indices[0] - 1
                    && index <= indices[indices.length - 1]) {
                indices = null;
                return true;
            }
        }

        DefaultListModel listModel = (DefaultListModel) target.getModel();
        int max = listModel.getSize();
        if (index < 0) {
            index = max;
        } else {
            index++;
            if (index > max) {
                index = max;
            }
        }
        addIndex = index;
        addCount = alist.size();
        for (int i = 0; i < alist.size(); i++) {
            listModel.add(index++, alist.get(i));
        }
        return true;
    }

    protected void exportDone(JComponent c, Transferable data, int action) {
        if ((action == MOVE) && (indices != null)) {
            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) {
                        indices[i] += addCount;
                    }
                }
            }
            for (int i = indices.length - 1; i >= 0; i--) {
                model.remove(indices[i]);
            }
        }
        indices = null;
        addIndex = -1;
        addCount = 0;
    }

    private boolean hasLocalArrayListFlavor(DataFlavor[] flavors) {
        if (localArrayListFlavor == null) {
            return false;
        }

        for (int i = 0; i < flavors.length; i++) {
            if (flavors[i].equals(localArrayListFlavor)) {
                return true;
            }
        }
        return false;
    }

    private boolean hasSerialArrayListFlavor(DataFlavor[] flavors) {
        if (serialArrayListFlavor == null) {
            return false;
        }

        for (int i = 0; i < flavors.length; i++) {
            if (flavors[i].equals(serialArrayListFlavor)) {
                return true;
            }
        }
        return false;
    }

    public boolean canImport(JComponent c, DataFlavor[] flavors) {
        if (hasLocalArrayListFlavor(flavors)) {
            return true;
        }
        if (hasSerialArrayListFlavor(flavors)) {
            return true;
        }
        return false;
    }

    protected Transferable createTransferable(JComponent c) {
        if (c instanceof JList) {
            source = (JList) c;
            indices = source.getSelectedIndices();
            Object[] values = source.getSelectedValues();
            if (values == null || values.length == 0) {
                return null;
            }
            ArrayList alist = new ArrayList(values.length);
            for (int i = 0; i < values.length; i++) {
                Object o = values[i];
                String str = o.toString();
                if (str == null) {
                    str = "";
                }
                alist.add(str);
            }
            return new ArrayListTransferable(alist);
        }
        return null;
    }

    public int getSourceActions(JComponent c) {
        return COPY_OR_MOVE;
    }

    public class ArrayListTransferable implements Transferable {

        ArrayList data;

        public ArrayListTransferable(ArrayList alist) {
            data = alist;
        }

        public Object getTransferData(DataFlavor flavor)
                throws UnsupportedFlavorException {
            if (!isDataFlavorSupported(flavor)) {
                throw new UnsupportedFlavorException(flavor);
            }
            return data;
        }

        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[]{localArrayListFlavor,
                serialArrayListFlavor};
        }

        public boolean isDataFlavorSupported(DataFlavor flavor) {
            if (localArrayListFlavor.equals(flavor)) {
                return true;
            }
            if (serialArrayListFlavor.equals(flavor)) {
                return true;
            }
            return false;
        }
    }
}
导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.datatransfer.DataFlavor;
导入java.awt.datatransfer.transfer;
导入java.awt.datatransfer.UnsupportedFlavorException;
导入java.io.IOException;
导入java.util.ArrayList;
导入javax.swing.BorderFactory;
导入javax.swing.DefaultListModel;
导入javax.swing.DropMode;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JList;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.ListSelectionModel;
导入javax.swing.TransferHandler;
公共类TestListReorder扩展了JPanel{
ArrayListTransferHandler arrayListHandler;
公共TestListReorder(){
arrayListHandler=新的ArrayListTransferHandler();
JList列表1、列表2;
DefaultListModel list1Model=新的DefaultListModel();
list1Model.addElement(“0(列表1)”;
列表1模型补遗(“1(列表1)”;
列表1模型补遗(“2(列表1)”;
列表1模型补遗(“3(列表1)”;
列表1模型补遗(“4(列表1)”;
列表1模型补遗(“5(列表1)”;
列表1模型补遗(“6(列表1)”;
list1=新的JList(list1模型);
列表1.setDropMode(DropMode.USE_选择);
list1.设置选择模式(ListSelectionModel.单间隔选择);
列表1.setTransferHandler(arrayListHandler);
列表1.setDragEnabled(真);
JScrollPane list1View=新的JScrollPane(list1);
list1View.setPreferredSize(新维度(200100));
JPanel panel1=新的JPanel();
panel1.setLayout(新的BorderLayout());
panel1.add(列表1视图,BorderLayout.CENTER);
panel1.setBorder(BorderFactory.CreateEmptyByOrder(5,5,5,5));
setLayout(新的BorderLayout());
添加(panel1,BorderLayout.LINE_START);
setBorder(BorderFactory.createEmptyByOrder(20,20,20,20));
}
/**
*创建GUI并显示它。为了线程安全,应该
*从事件调度线程调用。
*/
私有静态void createAndShowGUI(){
//确保我们有漂亮的窗户装饰。
JFrame.setDefaultLookAndFeelDecorated(true);
//创建并设置窗口。
JFrame=新JFrame(“DragListDemo”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//创建并设置内容窗格。
TestListReorder demo=新建TestListReorder();
frame.setContentPane(演示);
//显示窗口。
frame.pack();
frame.setVisible(true);
}
公共静态void main(字符串[]args){
//为事件调度线程计划作业:
//创建并显示此应用程序的GUI。
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
}
/*
*ArrayListTransferHandler.java由1.4 DragListDemo.java示例使用。
*/
类ArrayListTransferHandler扩展了TransferHandler{
DataFlavor localArrayListFlavor、serialArrayListFlavor;
字符串localArrayListType=DataFlavor.javaJVMLocalObjectMimeType
+“class=java.util.ArrayList”;
JList source=null;
int[]索引=null;
int addIndex=-1;//添加项的位置
int addCount=0;//添加的项目数
公共ArrayListTransferHandler(){
试一试{
localArrayListFlavor=新的DataFlavor(localArrayListType);
}catch(classnotfounde异常){
系统输出
.println(“ArrayListTransferHandler:无法创建数据样式”);
}
serialArrayListFlavor=新的DataFlavor(ArrayList.class,“ArrayList”);
}
公共布尔输入数据(JComponent c,t){
JList target=null;
ArrayList=null;
if(!canImport(c,t.getTransferDataFlavors()){
返回false;
}
试一试{
目标=(JList)c;
if(hasLocalArrayListFlavor(t.getTransferDataFlavors())){
alist=(ArrayList)t.getTransferData(localArrayListFlavor);
}else if(hasSerialArrayListFlavor(t.getTransferDataFlavors())){
alist=(ArrayList)t.getTransferData(serialArrayListFlavor);
}否则{
返回false;
}
}捕获(无支持的LavorUFE异常){
System.out.println(“importData:unsupported data flavor”);
返回false;
}捕获(ioe异常ioe){
System.out.println(“导入数据:I/O异常”);
返回false;
}
//此时,我们使用相同的代码检索数据
//本地或连续地。
//我们将删除当前选定的索引。
int index=target.getSelectedIndex();
//防止用户将数据放回自身。
//例如,如果用户正在移动项目4、5、6和7,以及
//尝试在项目#5之后插入项目,这将导致
//删除原始项目时可能会出现问题。
//这被解释为将相同的数据放在自身上
//而且没有效果。
if(源等于(目标)){
如果(索引!=null&&index>=索引[0]-1
&&索引(最大值){
指数=最大值;
}
protected void exportDone(JComponent c, Transferable data, int action) {
    if ((action == MOVE) && (indices != null)) {
        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.

        for (int i = indices.length - 1; i >= 0; i--)
            model.remove(indices[i]);

    }
    if (addCount > 0) {
        for (int i = 0; i < indices.length; i++) {
            if (indices[i] > addIndex) {
                indices[i] += addCount;
            }
        }
    }

    indices = null;
    addIndex = -1;
    addCount = 0;
}