如何将图像从一个面板拖到另一个面板[关闭]

Posted

技术标签:

【中文标题】如何将图像从一个面板拖到另一个面板[关闭]【英文标题】:How to drag an image from one panel to other [closed] 【发布时间】:2013-06-25 22:09:54 【问题描述】:

我创建了一个框架,然后在其中创建了面板。我已将图像放置在一个面板中,现在我需要将该图像拖到另一个面板中。我怎么能那样做。请作为初学者一步一步解释。

【问题讨论】:

“请逐步解释” 请查阅相关教程。 SO 是一个问答网站。 另外,当是你(I)时,请避免写i 请参考此链接。 [是否可以在 JFrame 中包含“可移动”/“可拖动”组件,例如 JButton、JTextFields?][1] [1]:***.com/questions/5052141/…希望这对您有所帮助。 我认为我的代码对你有帮助,请参阅此文档。 docs.oracle.com/javase/tutorial/uiswing/dnd/intro.html 你可以看看this example 【参考方案1】:

使用纯 java、DragGestureListenerDropTargetAdapterTransferHandler 的快速示例,用于 DnD 支持一个面板上的图像到另一个:

在单击和拖动任何形状之前:

选择绿色形状并拖动到上面的空白面板后:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
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.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.io.IOException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;
import javax.swing.border.TitledBorder;

public class Test 

    public static void main(String[] args) 
        createAndShowJFrame();
    

    public static void createAndShowJFrame() 
        SwingUtilities.invokeLater(new Runnable() 
            @Override
            public void run() 

                JFrame frame = createJFrame();
                frame.setVisible(true);

            
        );
    

    private static JFrame createJFrame() 
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        frame.setTitle("Test");

        JPanel panel = createEmptyJPanel();
        new MyDropTargetListener(panel);//this must be done or we wont be able to drop any image onto the empty panel

        frame.add(panel, BorderLayout.CENTER);

        try 
            frame.add(createJLabelPanel(), BorderLayout.SOUTH);
         catch (Exception ex) 
            ex.printStackTrace();
        

        frame.pack();

        return frame;
    

    private static JPanel createEmptyJPanel() 
        final JPanel p = new JPanel() 
            @Override
            public Dimension getPreferredSize() 
                return new Dimension(300, 300);
            
        ;
        p.setBorder(new TitledBorder("Drag Image onto this panel"));

        TransferHandler dnd = new TransferHandler() 
            @Override
            public boolean canImport(TransferSupport support) 
                if (!support.isDrop()) 
                    return false;
                
                //only Strings
                if (!support.isDataFlavorSupported(DataFlavor.imageFlavor)) 
                    return false;
                
                return true;
            

            @Override
            public boolean importData(TransferSupport support) 
                if (!canImport(support)) 
                    return false;
                

                Transferable tansferable = support.getTransferable();
                Icon ico;
                try 
                    ico = (Icon) tansferable.getTransferData(DataFlavor.imageFlavor);
                 catch (Exception e) 
                    e.printStackTrace();
                    return false;
                
                p.add(new JLabel(ico));
                return true;
            
        ;

        p.setTransferHandler(dnd);

        return p;
    

    private static JPanel createJLabelPanel() throws Exception 
        JPanel panel = new JPanel();
        panel.setBorder(new TitledBorder("Drag Image from here to Panel above"));

        JLabel label1 = new JLabel(new ImageIcon(new URL("http://i.stack.imgur.com/gJmeJ.png")));
        JLabel label2 = new JLabel(new ImageIcon(new URL("http://i.stack.imgur.com/8BGfi.png")));
        JLabel label3 = new JLabel(new ImageIcon(new URL("http://i.stack.imgur.com/1lgtq.png")));

        MyDragGestureListener dlistener = new MyDragGestureListener();
        DragSource ds1 = new DragSource();
        ds1.createDefaultDragGestureRecognizer(label1, DnDConstants.ACTION_COPY, dlistener);

        DragSource ds2 = new DragSource();
        ds2.createDefaultDragGestureRecognizer(label2, DnDConstants.ACTION_COPY, dlistener);

        DragSource ds3 = new DragSource();
        ds3.createDefaultDragGestureRecognizer(label3, DnDConstants.ACTION_COPY, dlistener);

        panel.add(label1);
        panel.add(label2);
        panel.add(label3);
        return panel;
    


class MyDropTargetListener extends DropTargetAdapter 

    private DropTarget dropTarget;
    private JPanel p;

    public MyDropTargetListener(JPanel panel) 
        p = panel;
        dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY, this, true, null);

    

    @Override
    public void drop(DropTargetDropEvent event) 
        try 
            DropTarget test = (DropTarget) event.getSource();
            Component ca = (Component) test.getComponent();
            Point dropPoint = ca.getMousePosition();
            Transferable tr = event.getTransferable();

            if (event.isDataFlavorSupported(DataFlavor.imageFlavor)) 
                Icon ico = (Icon) tr.getTransferData(DataFlavor.imageFlavor);

                if (ico != null) 

                    p.add(new JLabel(ico));
                    p.revalidate();
                    p.repaint();
                    event.dropComplete(true);
                
             else 
                event.rejectDrop();
            
         catch (Exception e) 
            e.printStackTrace();
            event.rejectDrop();
        
    


class MyDragGestureListener implements DragGestureListener 

    @Override
    public void dragGestureRecognized(DragGestureEvent event) 
        JLabel label = (JLabel) event.getComponent();
        final Icon ico = label.getIcon();


        Transferable transferable = new Transferable() 
            @Override
            public DataFlavor[] getTransferDataFlavors() 
                return new DataFlavor[]DataFlavor.imageFlavor;
            

            @Override
            public boolean isDataFlavorSupported(DataFlavor flavor) 
                if (!isDataFlavorSupported(flavor)) 
                    return false;
                
                return true;
            

            @Override
            public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException 
                return ico;
            
        ;
        event.startDrag(null, transferable);
    

【讨论】:

另见 this 回答 Swing 组件的拖放支持。 (接近我答案的结尾是带有屏幕截图的代码) +1 和 this ;) 仍然是低级拖动的粉丝?-) @kleopatra Lol 我不知何故知道你会找到这篇文章并在我正确的低级计数器部分纠正我:P。老实说,我打算把你的最后一个代码放进去,但我需要回去学习,*** 阻止了我,它就像一种药物 :) @user2530927 请参阅this 示例,该示例省略了DragGestureListener 以获得更高级别的实现。【参考方案2】:
    可能有多种方法可以实现您想要的。您可以使用玻璃窗格或 JXLayer,也可以 不要再将这两个面板视为单独的元素,而更像是进入大型虚拟空间的窗口。 此示例基本上将父组件视为两个图像窗格作为窗口的“虚拟空间”。 它们都共享相同的图像和图像位置详细信息。他们个人将图像位置(虚拟坐标)转换为局部坐标,并绘制尽可能多的图像... 鼠标控制由父级维护。这大大简化了流程,因为它可以同时通知两个面板

代码是……

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class CrossImage 

    public static void main(String[] args) 
        new CrossImage();
    

    public CrossImage() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                try 
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                 catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) 
                

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public class TestPane extends JPanel 

        private BufferedImage img;
        private ImagePane left;
        private ImagePane right;
        private Point imagePoint;

        public TestPane() 
            setBorder(new EmptyBorder(10, 10, 10, 10));
            setLayout(new GridLayout(0, 2, 10, 10));
            left = new ImagePane();
            right = new ImagePane();
            imagePoint = new Point(10, 10);
            left.setImageLocation(imagePoint);
            right.setImageLocation(imagePoint);
            try 
                img = ImageIO.read(new File("Background.jpg"));
                left.setImage(img);
                right.setImage(img);
             catch (IOException ex) 
                ex.printStackTrace();
            
            add(left);
            add(right);

            MouseAdapter mouseHandler = new MouseAdapter() 
                private Point delta;

                @Override
                public void mousePressed(MouseEvent e) 
                    Point origin = e.getPoint();
                    Rectangle bounds = new Rectangle(imagePoint, new Dimension(img.getWidth(), img.getHeight()));
                    if (bounds.contains(origin)) 
                        delta = new Point(origin.x - imagePoint.x, origin.y - imagePoint.y);
                    
                

                @Override
                public void mouseDragged(MouseEvent e) 
                    if (delta != null) 
                        imagePoint = e.getPoint();
                        imagePoint.translate(-delta.x, -delta.y);
                        left.setImageLocation(imagePoint);
                        right.setImageLocation(imagePoint);
                    
                

                @Override
                public void mouseReleased(MouseEvent e) 
                    delta = null;
                
            ;

            addMouseListener(mouseHandler);
            addMouseMotionListener(mouseHandler);
        
    

    public class ImagePane extends JPanel 

        private Image image;
        private Point imageLocation;

        public ImagePane() 
            setBorder(new LineBorder(Color.DARK_GRAY));
        

        @Override
        public Dimension getPreferredSize() 
            return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
        

        public void setImage(Image image) 
            this.image = image;
            repaint();
        

        public void setImageLocation(Point imageLocation) 
            this.imageLocation = imageLocation;
            repaint();
        

        @Override
        protected void paintComponent(Graphics g) 
            super.paintComponent(g);
            if (image != null && imageLocation != null) 
                Point p = SwingUtilities.convertPoint(getParent(), imageLocation, this);
                g.drawImage(image, p.x, p.y, this);
            
        
    

【讨论】:

星期五,评论日 :-) setImageLocation 中的坐标应该在 ImagePanel 的坐标中:它不知道是哪个客户端设置了它,假设它是父级是一个疯狂的猜测。反过来说,无论是谁设置了位置,都知道它的来源,并且可以安全地将它们转换为目标坐标

以上是关于如何将图像从一个面板拖到另一个面板[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

将包含 Swing 面板从一个容器移动到另一个容器后,OfficeBean 不会显示

统一拖拽,拖到其他UI元素后面

如何将对象从一个视图拖到另一个视图

将一个文件拖到另一个文件上并释放到底是做啥的?

如何将 UICollectionViewCell 从一个 UICollectionView 拖到另一个 UICollectionView?

如何在 XCode 的界面生成器中添加图像?