1 Востаннє редагувалося SnapeEye (07.11.2017 20:45:00)

Тема: DnD: JList(object) -> JPanel

Доброго дня!

Хочу зробити Drag and Drop систему для свого додатку. Треба захватити елемент JList, вкинути в якусь JPanel та на цiй панелi повинна з'явитись JLabel з текстом елементу, який захватували з JList.
Задумка такова:
https://image.prntscr.com/image/SwEtIysQTBqoZET-9C99qg.png

Питання: як написать механiзм для JList щоб передачи цiй панелi та для JPanel, яка буде приймати JLabel з текстом елементу, що був вибран в JList (додати в "drop" точку буде великим плюсом).

В интернетi куча статей з готовим кодом без будь-якого нормального пояснення чи щось примитивне типа текста з одного бокса в iнший... Може хтось поможе реалiзувати чи вкаже на нормальнi ресурси для вивчення?

Ось що намагався робити: drag елементу з JList, однак панель на "drop" не реагувала...
Може щось забув додати для JPanel чи для JList?

DataFlavor для перевiрки з класу Figure:

public static DataFlavor figure_flavor = new DataFlavor(JLabel.class, null);

JPanel:

JPanel panel = new JPanel();
PanelTH th = new PanelTH(panel);
panel.setTransferHandler(th);
PanelDropTarget target = new PanelDropTarget(panel);

private class PanelTH extends TransferHandler
{
    JPanel panel;
    public PanelTH(JPanel panel)
    {
        this.panel = panel;
    }
    public boolean canImport(TransferHandler.TransferSupport info)
    {
           if (!info.isDrop())
           {
                return false;
            }
            // we only import Strings
            if (!info.isDataFlavorSupported(DataFlavor.stringFlavor))
            {
                return false;
            }
            return true;
        }
        public boolean importData(TransferHandler.TransferSupport info)
        {
            // if we can't handle the import, say so
            if (!canImport(info))
            {
                return false;
            }
            // fetch the data and bail if this fails
            JLabel data;
            try
            {
                data = (JLabel) info.getTransferable().getTransferData(Figure.figure_flavor);
            }
            catch (UnsupportedFlavorException e)
            {
                return false;
            }
            catch (IOException e)
            {
                return false;
            }
            panel.add(data);
            panel.validate();
            
            return true;
        }
}
public class PanelDropTarget implements DropTargetListener
{
    protected JPanel pane;
    protected DropTarget dropTarget;
    protected boolean acceptableType; // Indicates whether data is acceptable
    protected DataFlavor targetFlavor; // Flavor to use for transfer
        
    public PanelDropTarget(JPanel pane)
    {
        this.pane = pane;
        // Create the DropTarget and register
        // it with the JPanel.
        dropTarget = new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE,
                this, true, null);
    }
    // Implementation of the DropTargetListener interface
    public void dragEnter(DropTargetDragEvent dtde)
    {
        // Get the type of object being transferred and determine
        // whether it is appropriate.
        checkTransferType(dtde);
        // Accept or reject the drag.
        acceptOrRejectDrag(dtde);
    }
    public void dragExit(DropTargetEvent dte)
    {}
    public void dragOver(DropTargetDragEvent dtde)
    {
        // Accept or reject the drag
        acceptOrRejectDrag(dtde);
    }
    public void dropActionChanged(DropTargetDragEvent dtde)
    {
        // Accept or reject the drag
        acceptOrRejectDrag(dtde);
    }
    public void drop(DropTargetDropEvent dtde)
    {
        // Check the drop action
        if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0)
        {
            // Accept the drop and get the transfer data
            dtde.acceptDrop(dtde.getDropAction());
            Transferable transferable = dtde.getTransferable();
            try
            {
                boolean result = dropComponent(transferable);
                dtde.dropComplete(result);
            }
            catch (Exception e)
            {
                dtde.dropComplete(false);
            }
        }
        else
        {
            dtde.rejectDrop();
        }
    }
    // Internal methods start here
    protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde)
    {
        int dropAction = dtde.getDropAction();
        int sourceActions = dtde.getSourceActions();
        boolean acceptedDrag = false;
        // Reject if the object being transferred
        // or the operations available are not acceptable.
        if (!acceptableType || (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0)
        {
            dtde.rejectDrag();
        }
        else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0)
        {
            // Not offering copy or move - suggest a copy
            dtde.acceptDrag(DnDConstants.ACTION_COPY);
            acceptedDrag = true;
        }
        else
        {
            // Offering an acceptable operation: accept
            dtde.acceptDrag(dropAction);
            acceptedDrag = true;
        }
        return acceptedDrag;
    }
    protected void checkTransferType(DropTargetDragEvent dtde)
    {
        // Only accept a flavor that returns a Component
        acceptableType = false;
        DataFlavor[] fl = dtde.getCurrentDataFlavors();
        for (int i = 0; i < fl.length; i++)
        {
            Class dataClass = fl[i].getRepresentationClass();
            if (Component.class.isAssignableFrom(dataClass))
            {
                // This flavor returns a Component - accept it.
                targetFlavor = fl[i];
                acceptableType = true;
                break;
            }
        }
    }
    protected boolean dropComponent(Transferable transferable) throws IOException, UnsupportedFlavorException
    {
        Object o = transferable.getTransferData(targetFlavor);
        if (o instanceof Component)
        {
            pane.add((Component) o);
            pane.validate();
            return true;
        }
        return false;
    }
}

JList:

JList list = new JList(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // Selection mode
list.setDragEnabled(true);
list.setTransferHandler(new ListTH());

private static class ListTH extends TransferHandler
{
    @Override
    public int getSourceActions(JComponent c)
    {
        return TransferHandler.COPY_OR_MOVE;
    }
        
    @Override
    protected Transferable createTransferable(JComponent source)
    {
        JList sourceList = (JList) source;
        Figure figure = (Figure) sourceList.getSelectedValue();
        Transferable t = new Transferable()
        {
            @Override
            public boolean isDataFlavorSupported(DataFlavor df)
            {
                for (DataFlavor current : getTransferDataFlavors())
                    if (current.equals(df))
                        return true;
                return false;
            }
            @Override
            public DataFlavor[] getTransferDataFlavors()
            {
                return new DataFlavor[]{Figure.figure_flavor};
            }
            @Override
            public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException
            {
                return new JLabel(figure.getFigureName());
            }
        } ;
        return t;
    }
}

Розраховую на Ваш свiжий погляд! Буду радий будь-якiй допомозi в вирiшеннi цього питання!

P.S. завантажую також проект.
JList - пакет commands - класс PluginController - метод getPluginList().
JPanel - пакет workspace, класс Workspace, конструктор

Post's attachments

PainterBlock.rar 420.83 kb, 286 downloads since 2017-11-07 

Подякували: 0xDADA11C7, /KIT\2