单击图像时 JFrame 图像更新
JFrame Image Update on click of image
tldr; 如何在 JFrame 对象(特别是 JLabel)上使用 MouseEvent 来更新 JFrame 中显示的图像
我正在尝试创建一个程序,将图像分解成图块,然后单击其中一个图块,程序会将图块移动到图像中打开的 space。 (有关详细信息,请参阅 Sliding Puzzle)。
我目前能够 select 图像,将图像分解成图块,然后“随机”删除其中一个图块。
我的下一步是,单击其中一个图块,将其与空图块交换(我将在稍后处理要交换的图块的“资格”,但现在,只是希望能够将 selected 的图块与当前的空白图块交换)
为了创建 3x3 网格的图像,我将 bufferedImage 分成 9 个相等的部分,“随机”空白其中一个图像,然后使用 GridLayout 在 jLabels 中显示图像以将它们排列起来。
当我将 mouseListeners 添加到每个 jLabel 时,我可以看到我正在进入 MouseListener,因为我可以看到如下所示的控制台日志消息“已单击”,但是,我无法根据需要更新图像.
如何在这些 JFrame JLabel 上使用 MouseEvent 来调用 ImageContainer 中的方法(即 move())并更新显示的图像?
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class ImageJumble extends JPanel {
static int difficulty = 0;
ImageContainer imageContainer;
JFrame jFrame = new JFrame("Image Jumble");
private void run() {
SwingUtilities.invokeLater(this::displayImage);
}
public static void main(String[] args) {
System.out.print("Please enter the difficulty level (1-3): ");
Scanner scanner = new Scanner(System.in);
difficulty = scanner.nextInt();
new ImageJumble().run();
}
private void displayImage() {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Please choose an image...");
FileNameExtensionFilter filter = new FileNameExtensionFilter("JPEG", "jpeg", "jpg", "png", "bmp", "gif");
fc.addChoosableFileFilter(filter);
BufferedImage image = null;
if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
File selectedFile = fc.getSelectedFile();
try {
image = ImageIO.read(selectedFile);
} catch (IOException ex) {
ex.printStackTrace();
}
}
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setSize(image.getWidth(), image.getHeight());
jFrame.setVisible(true);
jFrame.setLayout(new GridLayout(difficulty,difficulty,0,0));
imageContainer = new ImageContainer(image,difficulty);
createImage();
}
private void createImage() {
imageContainer.randomize();
JLabel[] jLabels = new JLabel[difficulty * difficulty];
for(int i = 0; i < jLabels.length; i++) {
JLabel jLabel = new JLabel(new ImageIcon(imageContainer.getBufferedImages().get(i)));
jFrame.add(jLabel);
jLabel.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println("Clicked!");
imageContainer.move(i);
jFrame.removeAll();
createImage();
}
});
}
}
}
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ImageContainer {
private List<BufferedImage> bufferedImages = new ArrayList<>();
private int blankLocation = 0;
public ImageContainer(BufferedImage image, int difficulty) {
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
g.drawImage(image, 0, 0, null);
int width = bi.getWidth();
int height = bi.getHeight();
int swidth = width / difficulty;
int sheight = height / difficulty;
for (int i = 0; i < difficulty; i++) {
for (int j = 0; j < difficulty; j++) {
BufferedImage bimg = bi.getSubimage(j * swidth, i * sheight, swidth, sheight);
bufferedImages.add(bimg);
}
}
}
public List<BufferedImage> getBufferedImages() {
return bufferedImages;
}
public void setBufferedImages(List<BufferedImage> bufferedImages) {
this.bufferedImages = bufferedImages;
}
public void randomize() {
int size = bufferedImages.size();
int width = bufferedImages.get(0).getWidth();
int height = bufferedImages.get(0).getHeight();
blankLocation = new Random().nextInt(size);
bufferedImages.set(blankLocation, new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB));
}
public void move(int i) {
bufferedImages.set(blankLocation,bufferedImages.get(i));
blankLocation = i;
}
}
创建自定义 JLabel class 以保持位置 (i):
class MyImageLabel extends JLabel {
private int position;
public MyImageLabel(Icon image,int position) {
super(image);
this.position=position;
}
public int getPosition()
{
return position;
}
}
Adapt createImage
来实例化这个 class 而不是 JLabel
s 并且在 mouseListener 中你可以调用 getPosition()
:
for(int i = 0; i < jLabels.length; i++) {
MyImageLabel jLabel = new MyImageLabel(new ImageIcon(imageContainer.getBufferedImages().get(i)),i);
jFrame.add(jLabel);
jLabel.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println("Clicked!");
imageContainer.move(jLabel.getPosition());
jFrame.removeAll();
createImage();
}
});
}
我的建议是不要在 JFrame 对象上调用 .add 和 .removeAll,而是使用 GridLayout 创建一个新的 JPanel 并使用 jframe.getContentPanel().add(labelsPanel)。如果它没有刷新,您可以在 JPanel 上调用 revalidate()。
不要remove/add组件。而只是交换图标。
- 将 JPanel 与在每个网格中包含一个 JLabel 的 GridLayout 结合使用
- 为每个 JLabel 添加一个 ImageIcon(一个除外)
- 为每个 JLabel 添加一个 MouseListner。
- 在 mouseClicked 事件中,您获取被单击的标签并删除 ImageIcon 并将图标添加到空标签。
因此,当您创建电路板时,您可以有一个像 emptyLabel
这样的变量,它会被初始化为没有图标的标签。那么 mouseClicked 中的逻辑可能是这样的:
JLabel clicked = (JLabel)e.getSource();
emptyLabel.setIcon( clicked.getIcon() );
emptyLabel = clicked;
此答案基于 this 之前的答案,并根据您的代码进行了调整。
它是一个 one-file mre : 整个代码可以是 copy-pasted 到 ImageJumble.java
文件,并且 运行。
它支持从任何网格位置到任何其他位置的 DnD。您可能想要更改它。
请注意评论:
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class ImageJumble extends JPanel {
private static int difficulty = 3;
private static final String FLOWER = "http://www.digitalphotoartistry.com/rose1.jpg";
private static final int GAP = 4;
private JPanel content;
private void run() {
SwingUtilities.invokeLater(this::displayImage);
}
public static void main(String[] args) {
new ImageJumble().run();
}
private void displayImage() {
BufferedImage bi = null;
try {
bi = ImageIO.read(new URL(FLOWER));
} catch (IOException ex) {
ex.printStackTrace();
}
content = new JPanel(new GridLayout(difficulty,difficulty, GAP,GAP));
createImage(bi);
JFrame jFrame = new JFrame("Image Jumble");
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.add(content);
jFrame.pack();
jFrame.setVisible(true);
}
private void createImage( BufferedImage bi) {
ImageContainer imageContainer = new ImageContainer(bi,difficulty);
imageContainer.randomize();
for(int i = 0; i < difficulty * difficulty; i++) {
content.add(new DragDropPane(imageContainer.getBufferedImages().get(i)));;
}
}
}
class ImageContainer {
private final List<BufferedImage> bufferedImages = new ArrayList<>();
private int blankLocation = 0;
public ImageContainer(BufferedImage image, int difficulty) {
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
g.drawImage(image, 0, 0, null);
int width = bi.getWidth();
int height = bi.getHeight();
int swidth = width / difficulty;
int sheight = height / difficulty;
for (int i = 0; i < difficulty; i++) {
for (int j = 0; j < difficulty; j++) {
BufferedImage bimg = bi.getSubimage(j * swidth, i * sheight, swidth, sheight);
bufferedImages.add(bimg);
}
}
}
public List<BufferedImage> getBufferedImages() {
return bufferedImages;
}
public void randomize() {
Collections.shuffle(bufferedImages);//shuffle images
int size = bufferedImages.size();
int width = bufferedImages.get(0).getWidth();
int height = bufferedImages.get(0).getHeight();
blankLocation = new Random().nextInt(size);
bufferedImages.set(blankLocation, new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB));
}
}
class DragDropPane extends JPanel implements DragGestureListener, DragSourceListener {
private JComponent dragable;
private final BufferedImage bi;
public DragDropPane(BufferedImage bi) {
setBackground(Color.BLACK);
this.bi = bi;
var label = new JLabel(new ImageIcon(bi), JLabel.CENTER);
setContent(label);
new MyDropTargetListener(this);
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
this, DnDConstants.ACTION_COPY, this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(bi.getWidth(), bi.getHeight());
}
public void setContent(JComponent component) {
removeAll();
dragable = component;
add(component);
repaint();
}
//-->DragGestureListener implementation
@Override
public void dragGestureRecognized(DragGestureEvent dge) {
// Create our transferable wrapper
Transferable transferable = new TransferableComponent(dragable);
// Start the "drag" process...
DragSource ds = dge.getDragSource();
ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
remove(dragable);
revalidate(); repaint();
}
//-->DragSourceListener implementation
@Override
public void dragEnter(DragSourceDragEvent dsde) {}
@Override
public void dragOver(DragSourceDragEvent dsde) {}
@Override
public void dropActionChanged(DragSourceDragEvent dsde) {}
@Override
public void dragExit(DragSourceEvent dse) {}
@Override
public void dragDropEnd(DragSourceDropEvent dsde) {
// If the drop was not successful, we need to
// return the component back to it's previous
// parent
if (!dsde.getDropSuccess()) {
setContent(dragable);
}
}
}
class MyDropTargetListener extends DropTargetAdapter {
private final DragDropPane target;
public MyDropTargetListener(DragDropPane target) {
this.target = target;
new DropTarget(target, DnDConstants.ACTION_COPY, this, true, null);
}
@Override
public void drop(DropTargetDropEvent event) {
try {
var tr = event.getTransferable();
var component = (JComponent) tr.getTransferData(TransferableComponent.component);
if (event.isDataFlavorSupported(TransferableComponent.component)) {
event.acceptDrop(DnDConstants.ACTION_COPY);
target.setContent(component);
event.dropComplete(true);
} else {
event.rejectDrop();
}
} catch (Exception e) {
e.printStackTrace();
event.rejectDrop();
}
}
}
class TransferableComponent implements Transferable {
protected static final DataFlavor component =
new DataFlavor(JComponent.class, "A Component");
protected static final DataFlavor[] supportedFlavors = {
component
};
private final JComponent componentToTransfer;
public TransferableComponent(JComponent componentToTransfer) {
this.componentToTransfer = componentToTransfer;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return supportedFlavors;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(component);
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (flavor.equals(component)) return componentToTransfer;
else throw new UnsupportedFlavorException(flavor);
}
}
tldr; 如何在 JFrame 对象(特别是 JLabel)上使用 MouseEvent 来更新 JFrame 中显示的图像
我正在尝试创建一个程序,将图像分解成图块,然后单击其中一个图块,程序会将图块移动到图像中打开的 space。 (有关详细信息,请参阅 Sliding Puzzle)。
我目前能够 select 图像,将图像分解成图块,然后“随机”删除其中一个图块。
我的下一步是,单击其中一个图块,将其与空图块交换(我将在稍后处理要交换的图块的“资格”,但现在,只是希望能够将 selected 的图块与当前的空白图块交换)
为了创建 3x3 网格的图像,我将 bufferedImage 分成 9 个相等的部分,“随机”空白其中一个图像,然后使用 GridLayout 在 jLabels 中显示图像以将它们排列起来。
当我将 mouseListeners 添加到每个 jLabel 时,我可以看到我正在进入 MouseListener,因为我可以看到如下所示的控制台日志消息“已单击”,但是,我无法根据需要更新图像.
如何在这些 JFrame JLabel 上使用 MouseEvent 来调用 ImageContainer 中的方法(即 move())并更新显示的图像?
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class ImageJumble extends JPanel {
static int difficulty = 0;
ImageContainer imageContainer;
JFrame jFrame = new JFrame("Image Jumble");
private void run() {
SwingUtilities.invokeLater(this::displayImage);
}
public static void main(String[] args) {
System.out.print("Please enter the difficulty level (1-3): ");
Scanner scanner = new Scanner(System.in);
difficulty = scanner.nextInt();
new ImageJumble().run();
}
private void displayImage() {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Please choose an image...");
FileNameExtensionFilter filter = new FileNameExtensionFilter("JPEG", "jpeg", "jpg", "png", "bmp", "gif");
fc.addChoosableFileFilter(filter);
BufferedImage image = null;
if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
File selectedFile = fc.getSelectedFile();
try {
image = ImageIO.read(selectedFile);
} catch (IOException ex) {
ex.printStackTrace();
}
}
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setSize(image.getWidth(), image.getHeight());
jFrame.setVisible(true);
jFrame.setLayout(new GridLayout(difficulty,difficulty,0,0));
imageContainer = new ImageContainer(image,difficulty);
createImage();
}
private void createImage() {
imageContainer.randomize();
JLabel[] jLabels = new JLabel[difficulty * difficulty];
for(int i = 0; i < jLabels.length; i++) {
JLabel jLabel = new JLabel(new ImageIcon(imageContainer.getBufferedImages().get(i)));
jFrame.add(jLabel);
jLabel.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println("Clicked!");
imageContainer.move(i);
jFrame.removeAll();
createImage();
}
});
}
}
}
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ImageContainer {
private List<BufferedImage> bufferedImages = new ArrayList<>();
private int blankLocation = 0;
public ImageContainer(BufferedImage image, int difficulty) {
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
g.drawImage(image, 0, 0, null);
int width = bi.getWidth();
int height = bi.getHeight();
int swidth = width / difficulty;
int sheight = height / difficulty;
for (int i = 0; i < difficulty; i++) {
for (int j = 0; j < difficulty; j++) {
BufferedImage bimg = bi.getSubimage(j * swidth, i * sheight, swidth, sheight);
bufferedImages.add(bimg);
}
}
}
public List<BufferedImage> getBufferedImages() {
return bufferedImages;
}
public void setBufferedImages(List<BufferedImage> bufferedImages) {
this.bufferedImages = bufferedImages;
}
public void randomize() {
int size = bufferedImages.size();
int width = bufferedImages.get(0).getWidth();
int height = bufferedImages.get(0).getHeight();
blankLocation = new Random().nextInt(size);
bufferedImages.set(blankLocation, new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB));
}
public void move(int i) {
bufferedImages.set(blankLocation,bufferedImages.get(i));
blankLocation = i;
}
}
创建自定义 JLabel class 以保持位置 (i):
class MyImageLabel extends JLabel {
private int position;
public MyImageLabel(Icon image,int position) {
super(image);
this.position=position;
}
public int getPosition()
{
return position;
}
}
Adapt createImage
来实例化这个 class 而不是 JLabel
s 并且在 mouseListener 中你可以调用 getPosition()
:
for(int i = 0; i < jLabels.length; i++) {
MyImageLabel jLabel = new MyImageLabel(new ImageIcon(imageContainer.getBufferedImages().get(i)),i);
jFrame.add(jLabel);
jLabel.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println("Clicked!");
imageContainer.move(jLabel.getPosition());
jFrame.removeAll();
createImage();
}
});
}
我的建议是不要在 JFrame 对象上调用 .add 和 .removeAll,而是使用 GridLayout 创建一个新的 JPanel 并使用 jframe.getContentPanel().add(labelsPanel)。如果它没有刷新,您可以在 JPanel 上调用 revalidate()。
不要remove/add组件。而只是交换图标。
- 将 JPanel 与在每个网格中包含一个 JLabel 的 GridLayout 结合使用
- 为每个 JLabel 添加一个 ImageIcon(一个除外)
- 为每个 JLabel 添加一个 MouseListner。
- 在 mouseClicked 事件中,您获取被单击的标签并删除 ImageIcon 并将图标添加到空标签。
因此,当您创建电路板时,您可以有一个像 emptyLabel
这样的变量,它会被初始化为没有图标的标签。那么 mouseClicked 中的逻辑可能是这样的:
JLabel clicked = (JLabel)e.getSource();
emptyLabel.setIcon( clicked.getIcon() );
emptyLabel = clicked;
此答案基于 this 之前的答案,并根据您的代码进行了调整。
它是一个 one-file mre : 整个代码可以是 copy-pasted 到 ImageJumble.java
文件,并且 运行。
它支持从任何网格位置到任何其他位置的 DnD。您可能想要更改它。
请注意评论:
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class ImageJumble extends JPanel {
private static int difficulty = 3;
private static final String FLOWER = "http://www.digitalphotoartistry.com/rose1.jpg";
private static final int GAP = 4;
private JPanel content;
private void run() {
SwingUtilities.invokeLater(this::displayImage);
}
public static void main(String[] args) {
new ImageJumble().run();
}
private void displayImage() {
BufferedImage bi = null;
try {
bi = ImageIO.read(new URL(FLOWER));
} catch (IOException ex) {
ex.printStackTrace();
}
content = new JPanel(new GridLayout(difficulty,difficulty, GAP,GAP));
createImage(bi);
JFrame jFrame = new JFrame("Image Jumble");
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.add(content);
jFrame.pack();
jFrame.setVisible(true);
}
private void createImage( BufferedImage bi) {
ImageContainer imageContainer = new ImageContainer(bi,difficulty);
imageContainer.randomize();
for(int i = 0; i < difficulty * difficulty; i++) {
content.add(new DragDropPane(imageContainer.getBufferedImages().get(i)));;
}
}
}
class ImageContainer {
private final List<BufferedImage> bufferedImages = new ArrayList<>();
private int blankLocation = 0;
public ImageContainer(BufferedImage image, int difficulty) {
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
g.drawImage(image, 0, 0, null);
int width = bi.getWidth();
int height = bi.getHeight();
int swidth = width / difficulty;
int sheight = height / difficulty;
for (int i = 0; i < difficulty; i++) {
for (int j = 0; j < difficulty; j++) {
BufferedImage bimg = bi.getSubimage(j * swidth, i * sheight, swidth, sheight);
bufferedImages.add(bimg);
}
}
}
public List<BufferedImage> getBufferedImages() {
return bufferedImages;
}
public void randomize() {
Collections.shuffle(bufferedImages);//shuffle images
int size = bufferedImages.size();
int width = bufferedImages.get(0).getWidth();
int height = bufferedImages.get(0).getHeight();
blankLocation = new Random().nextInt(size);
bufferedImages.set(blankLocation, new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB));
}
}
class DragDropPane extends JPanel implements DragGestureListener, DragSourceListener {
private JComponent dragable;
private final BufferedImage bi;
public DragDropPane(BufferedImage bi) {
setBackground(Color.BLACK);
this.bi = bi;
var label = new JLabel(new ImageIcon(bi), JLabel.CENTER);
setContent(label);
new MyDropTargetListener(this);
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
this, DnDConstants.ACTION_COPY, this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(bi.getWidth(), bi.getHeight());
}
public void setContent(JComponent component) {
removeAll();
dragable = component;
add(component);
repaint();
}
//-->DragGestureListener implementation
@Override
public void dragGestureRecognized(DragGestureEvent dge) {
// Create our transferable wrapper
Transferable transferable = new TransferableComponent(dragable);
// Start the "drag" process...
DragSource ds = dge.getDragSource();
ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
remove(dragable);
revalidate(); repaint();
}
//-->DragSourceListener implementation
@Override
public void dragEnter(DragSourceDragEvent dsde) {}
@Override
public void dragOver(DragSourceDragEvent dsde) {}
@Override
public void dropActionChanged(DragSourceDragEvent dsde) {}
@Override
public void dragExit(DragSourceEvent dse) {}
@Override
public void dragDropEnd(DragSourceDropEvent dsde) {
// If the drop was not successful, we need to
// return the component back to it's previous
// parent
if (!dsde.getDropSuccess()) {
setContent(dragable);
}
}
}
class MyDropTargetListener extends DropTargetAdapter {
private final DragDropPane target;
public MyDropTargetListener(DragDropPane target) {
this.target = target;
new DropTarget(target, DnDConstants.ACTION_COPY, this, true, null);
}
@Override
public void drop(DropTargetDropEvent event) {
try {
var tr = event.getTransferable();
var component = (JComponent) tr.getTransferData(TransferableComponent.component);
if (event.isDataFlavorSupported(TransferableComponent.component)) {
event.acceptDrop(DnDConstants.ACTION_COPY);
target.setContent(component);
event.dropComplete(true);
} else {
event.rejectDrop();
}
} catch (Exception e) {
e.printStackTrace();
event.rejectDrop();
}
}
}
class TransferableComponent implements Transferable {
protected static final DataFlavor component =
new DataFlavor(JComponent.class, "A Component");
protected static final DataFlavor[] supportedFlavors = {
component
};
private final JComponent componentToTransfer;
public TransferableComponent(JComponent componentToTransfer) {
this.componentToTransfer = componentToTransfer;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return supportedFlavors;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(component);
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (flavor.equals(component)) return componentToTransfer;
else throw new UnsupportedFlavorException(flavor);
}
}