Плъзгане и пускане на изображения

Правя програма за редактиране на изображения в Java. Чудех се дали е възможно да плъзнете изображение от работния плот на потребителя върху JPanel и да зададете изображението, което е плъзнато, като фон на JPanel. Възможно ли е това в Java? Ако е така, как бих го направил?


person Jonathan Beaudoin    schedule 16.09.2012    source източник
comment
Вярвам, че е възможно, но аз самият все още не съм го направил. Търсили ли сте в Google и оценявали ли сте уроците за 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