Reputation: 1
I have created a Swing application that can import images into a label, but what I want to do is to put the imported image into an internal frame that will be created after the image is dropped.
JInternalFrame
JFrame
public class Test{
public static void main(String[] args) {
JFrame f = new JFrame("Testing");
JLabel l = new JLabel("Drop here");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 600);
f.setLocationRelativeTo(null);
f.setVisible(true);
f.add(l);
l.setHorizontalAlignment(JLabel.CENTER);
l.setTransferHandler(new TransferHandler() {
private static final long serialVersionUID = 1L;
public static final DataFlavor[] SUPPORTED_DATA_FLAVORS = new DataFlavor[]{
DataFlavor.javaFileListFlavor,
DataFlavor.imageFlavor
};
@Override
public boolean canImport(TransferHandler.TransferSupport support) {
System.out.println("1");
for (DataFlavor flavor : SUPPORTED_DATA_FLAVORS) {
if (!support.isDataFlavorSupported(flavor)) {
return true;
}
}
return true;
}
@Override
public boolean importData(TransferHandler.TransferSupport support) {
System.out.println("2");
new Test();
JInternalFrame mb = new JInternalFrame("Frame title4", true, true, true);
JLabel la = new JLabel("here");
mb.setSize(400, 300);
l.add(mb);
la.setHorizontalAlignment(JLabel.CENTER);
mb.add(la);
mb.setVisible(true);
if (canImport(support)) {
try {
Transferable t = support.getTransferable();
Component component = support.getComponent();
if (component instanceof JLabel) {
Image image = null;
if (support.isDataFlavorSupported(DataFlavor.imageFlavor)) {
image = (Image) t.getTransferData(DataFlavor.imageFlavor);
} else if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
@SuppressWarnings("rawtypes")
List files = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
if (files.size() > 0) {
image = ImageIO.read((File) files.get(0));
}
}
ImageIcon icon = null;
if (image != null) {
icon = new ImageIcon(image);
}
((JLabel) component).setIcon(icon);
return true;
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
return true;
}
});
}}
Upvotes: 0
Views: 152
Reputation: 347184
Drop and image on a frame, panel, label, internal frame, is all effectively the same thing. For me, I'd focus on common denominator to make things easier, for me, this means a JPanel
.
A JPanel
can be added to a frame, internal frame another panel/container and can make decisions about how to present the drop, in this case, it can use a JLabel
to present an image.
So, based on how to drag and drop files from a directory in java and Java Drag-n-Drop files of specific extension on JFrame
You could do something like...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.TooManyListenersException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JInternalFrame littleFrame = new JInternalFrame("Hello", true, true, true, true);
littleFrame.add(new DropPane());
littleFrame.pack();
littleFrame.setVisible(true);
JDesktopPane desktopPane = new JDesktopPane();
desktopPane.add(littleFrame);
desktopPane.setPreferredSize(new Dimension(400, 400));
JFrame frame = new JFrame();
frame.add(desktopPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DropPane extends JPanel {
private DropTarget dropTarget;
private DropTargetHandler dropTargetHandler;
private Point dragPoint;
private boolean dragAccepted;
private boolean dragOver = false;
private JLabel message;
public DropPane() {
setLayout(new GridBagLayout());
message = new JLabel();
add(message);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected DropTarget getMyDropTarget() {
if (dropTarget == null) {
dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, null);
}
return dropTarget;
}
protected DropTargetHandler getDropTargetHandler() {
if (dropTargetHandler == null) {
dropTargetHandler = new DropTargetHandler();
}
return dropTargetHandler;
}
@Override
public void addNotify() {
super.addNotify();
try {
getMyDropTarget().addDropTargetListener(getDropTargetHandler());
} catch (TooManyListenersException ex) {
ex.printStackTrace();
}
}
@Override
public void removeNotify() {
super.removeNotify();
getMyDropTarget().removeDropTargetListener(getDropTargetHandler());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (dragOver) {
Graphics2D g2d = (Graphics2D) g.create();
if (dragAccepted) {
g2d.setColor(new Color(0, 255, 0, 64));
} else {
g2d.setColor(new Color(255, 0, 0, 64));
}
g2d.fill(new Rectangle(getWidth(), getHeight()));
if (dragPoint != null) {
int x = dragPoint.x - 25;
int y = dragPoint.y - 25;
g2d.setColor(Color.BLACK);
g2d.drawRect(x, y, 50, 50);
}
g2d.dispose();
}
}
protected void importedImage(final Image image) {
Runnable run = new Runnable() {
@Override
public void run() {
if (image == null) {
message.setIcon(null);
} else {
message.setIcon(new ImageIcon(image));
}
}
};
SwingUtilities.invokeLater(run);
}
protected void importFailed(final String message) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(DropPane.this, message, "Error", JOptionPane.ERROR_MESSAGE);
}
});
}
protected class DropTargetHandler implements DropTargetListener {
private String[] validExtenions = new String[]{
".png", ".jpeg", ".jpeg", "bmp", "gif"
};
protected boolean canAcceptFile(File file) {
String name = file.getName().toLowerCase();
for (String ext : validExtenions) {
if (name.endsWith(ext)) {
return true;
}
}
return false;
}
protected File acceptableFileFrom(Transferable transferable) throws UnsupportedFlavorException, IOException {
Object transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor);
if (transferData == null) {
return null;
}
List fileList = (List) transferData;
if (fileList.size() > 1) {
return null;
}
File file = (File) fileList.get(0);
if (canAcceptFile(file)) {
return file;
}
return null;
}
protected boolean canAcceptDrag(Transferable transferable) {
if (transferable == null) {
return true;
}
try {
File file = acceptableFileFrom(transferable);
if (file == null) {
return true;
}
} catch (UnsupportedFlavorException | IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
return false;
}
protected boolean acceptsDrag(DropTargetDragEvent dtde) {
if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
Transferable transferable = dtde.getTransferable();
if (DropTargetHandler.this.canAcceptDrag(transferable)) {
dtde.acceptDrag(DnDConstants.ACTION_COPY);
return true;
} else {
dtde.rejectDrag();
return false;
}
} else {
dtde.rejectDrag();
return false;
}
}
@Override
public void dragEnter(DropTargetDragEvent dtde) {
boolean accepted = acceptsDrag(dtde);
SwingUtilities.invokeLater(new DragUpdate(true, dtde.getLocation(), accepted));
repaint();
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
boolean accepted = acceptsDrag(dtde);
SwingUtilities.invokeLater(new DragUpdate(true, dtde.getLocation(), accepted));
repaint();
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
@Override
public void dragExit(DropTargetEvent dte) {
SwingUtilities.invokeLater(new DragUpdate(false, null, false));
repaint();
}
@Override
public void drop(DropTargetDropEvent dtde) {
SwingUtilities.invokeLater(new DragUpdate(false, null, false));
importedImage(null);
if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dtde.acceptDrop(dtde.getDropAction());
try {
Transferable transferable = dtde.getTransferable();
File file = acceptableFileFrom(transferable);
if (file == null) {
importFailed("Not a supported image file");
dtde.dropComplete(false);
} else {
BufferedImage image = ImageIO.read(file);
dtde.dropComplete(true);
importedImage(image);
}
} catch (Exception ex) {
ex.printStackTrace();
dtde.dropComplete(false);
importFailed("Not a supported image format");
}
} else {
dtde.rejectDrop();
}
}
}
public class DragUpdate implements Runnable {
private boolean dragOver;
private Point dragPoint;
private boolean accepted;
public DragUpdate(boolean dragOver, Point dragPoint, boolean accepted) {
this.dragOver = dragOver;
this.dragPoint = dragPoint;
this.accepted = accepted;
}
@Override
public void run() {
DropPane.this.dragOver = dragOver;
DropPane.this.dragPoint = dragPoint;
DropPane.this.dragAccepted = accepted;
DropPane.this.repaint();
}
}
}
}
nb: On MacOS, you can't pre-process the Transferable
data. It did work on Windows way back when I was using Windows 7, I can't verify if it still works.
Upvotes: 1