Перетаскивание изображений

Я делаю программу для редактирования изображений на Java. Мне было интересно, можно ли перетащить изображение с рабочего стола пользователя на JPanel и установить изображение, которое было перетащено, в качестве фона для JPanel. Возможно ли это в Java? Если да, то как бы я это сделал?


person Jonathan Beaudoin    schedule 16.09.2012    source источник
comment
Я верю, что это возможно, но я еще не сделал этого сам. Вы гуглили и изучали учебные пособия по Java Drag & Drop? Если бы мне нужна была эта функциональность, я бы начал именно с этого и, конечно же, с поиска в stackoverflow. Удачи!   -  person Hovercraft Full Of Eels    schedule 16.09.2012
comment
Редактировать: чем больше я смотрю, тем сложнее это кажется. Опять же, это не кажется невозможным, но я еще не нашел простого прямого решения.   -  person Hovercraft Full Of Eels    schedule 16.09.2012
comment
Если это редактор изображений, почему выбранное изображение устанавливается в качестве фона для чего-либо?   -  person Andrew Thompson    schedule 16.09.2012


Ответы (1)


Короткий ответ: да, это возможно.

Есть несколько способов сделать это, я приведу код самого простого: перетаскивание файла изображения откуда-то в ваше Swing-приложение. Однако вы также можете скопировать изображение в буфер обмена из графического редактора и вставить его туда, но я думаю, что вам это не нужно. Чтобы реализовать этот второй вариант использования, вам придется использовать DataFlavor.imageFlavor вместо DataFlavor.javaFileListFlavor, как показано в моем примере. Итак, чтобы протестировать приведенный ниже код, просто добавьте экземпляр MainPanel в контейнер и, когда приложение запустится, перетащите файлы изображений на панель.

Это реализация TransferHandler:

import java.awt.Cursor;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.TransferHandler;

public class ImageTransferHandler extends TransferHandler {
    private static final DataFlavor FILE_FLAVOR = DataFlavor.javaFileListFlavor;

    private MainPanel mainPanel;

    public ImageTransferHandler(MainPanel panel) {
        mainPanel = panel;
    }

    /**
     * The method to handle the transfer between the source of data and the
     * destination, which is in our case the main panel.
     */
    public boolean importData(JComponent c, Transferable t) {
        if (canImport(c, t.getTransferDataFlavors())) {
            if (transferFlavor(t.getTransferDataFlavors(), FILE_FLAVOR)) {
                try {
                    List<File> fileList = (List<File>) t.getTransferData(FILE_FLAVOR);
                    if (fileList != null && fileList.toArray() instanceof File[]) {
                        File[] files = (File[]) fileList.toArray();
                        mainPanel.addFiles(files);
                    }
                    return true;
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (UnsupportedFlavorException ex) {
                    ex.printStackTrace();
                }
            }
        }
        return false;
    }

    /**
     * Returns the type of transfer actions to be supported.
     */
    public int getSourceActions(JComponent c) {
        return COPY_OR_MOVE;
    }

    /**
     * Specifies the actions to be performed after the data has been exported.
     */
    protected void exportDone(JComponent c, Transferable data, int action) {
        c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    /**
     * Returns true if the specified flavor is contained in the flavors array,
     * false otherwise.
     */
    private boolean transferFlavor(DataFlavor[] flavors, DataFlavor flavor) {
        boolean found = false;
        for (int i = 0; i < flavors.length && !found; i++) {
            found = flavors[i].equals(flavor);
        }
        return found;
    }

    /**
     * Returns true if the component can import the specified flavours, false
     * otherwise.
     */
    public boolean canImport(JComponent c, DataFlavor[] flavors) {
        for (int i = 0; i < flavors.length; i++) {
            if (FILE_FLAVOR.equals(flavors[i])) {
                return true;
            }
        }
        return false;
    }
}

Это панель, на которую я добавляю TransferHandler и которая отрисовывает изображение в качестве фона:

public class MainPanel extends JPanel {
    private Image image;

    MainPanel() {
        setTransferHandler(new ImageTransferHandler(this));
    }

    void addFiles(File[] files) {
        for (File file : files) {
            try {
                image = ImageIO.read(file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (image != null) {
            repaint();
        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        int width = getWidth();
        int height = getHeight();
        drawImage((Graphics2D) g, width, height);
    }

    private void drawImage(Graphics2D g2, int width, int height) {
        if (image != null) {
            g2.drawImage(image, 0, 0, width, height, null);
        } else {
            g2.drawRect(10, 10, width - 20, height - 20);
        }
    }
}
person Dan D.    schedule 16.09.2012