Java中的Drag and Drop详解与代码示例

Java中的Drag and Drop详解与代码示例 (转)

通过两种方法实现Drag and Drop:
  1.比较初级的D&D:只利用java.awt.datatransfer.*中的类实现.
 2.高级D&D: 利用javax.awt.dnd.*中的类实现.

比较初级D&D:只利用java.awt.datatransfer.*中的类实现.
 这种方法只支持对JComponent的拖拽.
 Drag and Drop的问题简单的说要涉及到两个部分: Drag Source, Drop target和Transferable 即从哪里drag来的, 以及drop到哪里去, 以及传输的数据.
 
 Drag Source可以分为两种:
 1.第一种是这样的JComponent, 他们有dragEnabled属性.这些JComponent包括:
javax.swing.JColorChooser
javax.swing.JFileChooser
javax.swing.JList
javax.swing.JTable
javax.swing.JTree
javax.swing.text.JTextComponent
 这些JComponent要想作为一个Drag Source只要调用setDragEnabled( true)即可, 不用多余的操作.
 2. 另一种Drag Source没有dragEnabled属性, 也就没有setDragEnabled方法, 要想作为Drag Source, 那就要给Component添加MouseMotionListener, 并实现mouseDragged方法, 后面会举例介绍.
 
 Drop Target, 任何JComponent都可以作为Drop Target, 但是也只有JComponent以及它的子类可以作为Drop Target, 其它的不行.
 
 Transferable
 所有的Transferable都是javax.swing.Transferable的子类, 但是细分还是可以分为两种情况:
 第一种是利用javax.swing.Transferable, 因为javax.swing.Transferable 是一个具体类我们可以直接调用new TransferHandler( String property )生成的transfer handler 作为Component的Transfer Handler, 这样的transfer handler可以将 Java Bean 属性从一个组件传输到另一个组件的传输处理程序。
 第二种则是自定义一个TransferHandler的子类, 你可以在这个类中实现复杂的拖拽操作.
下面有两个例子.
第一个例子用简单的javax.swing.Transferable, 第二个例子定义一个javax.swing.Transferable的子类.
例一

import  java.awt. * ;
import  java.awt.event. * ;
import  javax.swing. * ;
import  javax.swing.event. * ;

public   class  LabelDnd   ... {
    
private JFrame mainFrame;
    
private JPanel mainPanel;
    
private JLabel label;
    
private JTextField textField;
    
private JColorChooser colorChooser;
    
    
private JMenuBar menuBar = new JMenuBar();
    
private JMenu  menu = new JMenu( "Menu" );
    
private JMenuItem menuItem = new JMenuItem( "Handle Foregound" );
    
private TransferHandler t1 = new TransferHandler( "text" ) ;
    
private TransferHandler t2 = new TransferHandler( "foreground" );
    
public LabelDnd() ...{
        mainFrame 
= new JFrame();
        mainPanel 
= new JPanel( new BorderLayout() );
        label 
= new JLabel( "label" );
        label.setTransferHandler( t1 );
        
        menuItem.addActionListener( 
new ActionListener() ...{
            
public void actionPerformed( ActionEvent e ) ...{
                
if( label.getTransferHandler().equals( t1 ) ) ...{
                    LabelDnd.
this.menuItem.setText( "Handle Text" );
                    label.setTransferHandler( t2 );
                }
 else ...{
                    LabelDnd.
this.menuItem.setText( "Handle Foreground" );
                    label.setTransferHandler( t1 );
                }

            }

        }
);
        menu.add( menuItem );
        menu.setTransferHandler( t1 );
        menuBar.add( menu );
        mainFrame.setJMenuBar( menuBar );
        label.addMouseListener( 
new MouseAdapter() ...{
            
public void mousePressed( MouseEvent e ) ...{
                JComponent c 
= (JComponent)e.getSource();
                TransferHandler handler 
= c.getTransferHandler();
                handler.exportAsDrag( c, e, TransferHandler.COPY );
            }

        }
);
        textField 
= new JTextField( 20 );
        textField.setDragEnabled( 
true );
        colorChooser 
= new JColorChooser();
        colorChooser.setDragEnabled( 
true );
        mainPanel.add( label, BorderLayout.PAGE_START );
        mainPanel.add( textField, BorderLayout.PAGE_END );
        mainPanel.add( colorChooser, BorderLayout.WEST );
        mainFrame.getContentPane().add( mainPanel );
        mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        mainFrame.pack();
        mainFrame.setLocationRelativeTo( 
null );
        mainFrame.setVisible( 
true );
    }

    
public static void main( String[] args ) ...{
        
new LabelDnd();
    }

}


效果如下:

你可以试着拖拽下。

例二
PictureDnd.java

package  dt;
import  java.awt. * ;
import  javax.swing. * ;
import  java.awt.event. * ;
import  javax.swing.event. * ;

import  demo.gui.PictureComponent;

import  java.awt.datatransfer. * ;
import  java.io. * ;

public   class  PictureDnd  ... {
    JFrame mainFrame;
    JPanel mainPanel;
    PictureComponent[] pictures;
    
    
public static void main( String[]  args ) ...{
        
new PictureDnd();
    }

    
public PictureDnd() ...{
        mainFrame 
= new JFrame();
        mainPanel 
= new JPanel( new GridLayout( 22 ) );
        pictures 
=  new PictureComponent[ 4 ];
        pictures[ 
0 ] = new PictureComponent( new ImageIcon( "Sunset.jpg" ).getImage() );
        pictures[ 
1 ] = new PictureComponent( new ImageIcon( "Winter.jpg" ).getImage() );
        pictures[ 
2 ] = new PictureComponent( null );
        pictures[ 
3 ] = new PictureComponent( null );
        
        mainPanel.add( pictures[ 
0 ] );
        mainPanel.add( pictures[ 
1 ] );
        mainPanel.add( pictures[ 
2 ] );
        mainPanel.add( pictures[ 
3 ] );
        
        mainPanel.setBorder( BorderFactory.createEmptyBorder( 
20202020 ) );
        mainFrame.getContentPane().add( mainPanel );
        mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        mainFrame.setSize( 
350400 );
        mainFrame.setLocationRelativeTo( 
null );
        mainFrame.setVisible( 
true );
    }

}

PicrureComponent.java

package  demo.gui;
import  java.awt.Color;
import  java.awt.Dimension;
import  java.awt.Graphics;
import  java.awt.Image;
import  java.awt.event.FocusEvent;
import  java.awt.event.FocusListener;
import  java.awt.event.MouseEvent;
import  java.awt.event.MouseListener;
import  java.util.HashSet;

import  javax.swing.JComponent;

public   class  PictureComponent  extends  JComponent 
implements  FocusListener, MouseListener  ... {
    Image image;
    HashSet
< PictureComponent > pcs = new HashSet< PictureComponent >();
    
public PictureComponent( Image image ) ...{
        
this.image = image;
        setPreferredSize( 
new Dimension(125125 ) );
        setFocusable( 
true );
        setTransferHandler( 
new PictureTransferHandler() );
        addFocusListener( 
this );
        addMouseListener( 
this );
    }

    
public HashSet< PictureComponent > getPcs() ...{
        
return this.pcs;
    }

    
public void setPcs( HashSet< PictureComponent > pcs ) ...{
        
this.pcs = pcs;
    }

    
public Image getImage() ...{
        
return this.image;
    }

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

    
public void paintComponent( Graphics graphics )...{
        Graphics g 
= graphics.create();
        g.setColor( Color.white );
        g.fillRect( 
00,  125,125 );
        
if( image != null ) ...{
            g.drawImage( image, 
00125125, Color.BLACK, this );
        }

        
if( isFocusOwner() ) ...{
            g.setColor( Color.red );
        }

        
else ...{
            g.setColor( Color.black );
        }

        g.drawRect( 
00125125 );
        g.dispose();
    }

    
public void focusGained( FocusEvent e ) ...{
        repaint();
    }

    
public void focusLost( FocusEvent e ) ...{
        repaint();
    }

    
public void mouseClicked( MouseEvent e ) ...{
        requestFocusInWindow();
    }

    
public void mouseEntered( MouseEvent e ) ...{}
    
public void mousePressed( MouseEvent e ) ...{}
    
public void mouseExited( MouseEvent e ) ...{}
    
public void mouseReleased( MouseEvent e ) ...{}
}

TransferablePicture:

package  demo.gui;
import  java.awt.Image;
import  java.awt.datatransfer.DataFlavor;
import  java.awt.datatransfer.Transferable;

/**/ /* Transferalbe */
public   class  TransferablePicture  implements  Transferable  ... {
    DataFlavor[] flavors 
= ...{ DataFlavor.imageFlavor };
    Image image;
    
public TransferablePicture( Image image ) ...{
        
this.image = image;
    }

    
public DataFlavor[] getTransferDataFlavors() ...{
        
return flavors;
    }

    
public Object getTransferData( DataFlavor flavor ) ...{
        
if( flavor.equals( DataFlavor.imageFlavor ) ) ...{
            
return image;
        }

        
return null;
    }

    
public boolean isDataFlavorSupported( DataFlavor flavor ) ...{
        
return flavor.equals( DataFlavor.imageFlavor );
    }

}

PictureTransferHandler.java

package  demo.gui;
import  java.awt.Image;
import  java.awt.datatransfer.DataFlavor;
import  java.awt.datatransfer.Transferable;
import  java.awt.datatransfer.UnsupportedFlavorException;
import  java.io.IOException;

import  javax.swing.Icon;
import  javax.swing.ImageIcon;
import  javax.swing.JComponent;
import  javax.swing.TransferHandler;

import  dt.TransferablePicture;

/**/ /* Transfer Handler */
class  PictureTransferHandler  extends  TransferHandler  ... {
    
public Transferable createTransferable( JComponent c ) ...{
        PictureComponent pc 
= (PictureComponent)c;
        
return new TransferablePicture( pc.getImage() );
    }

    
public boolean canImport( JComponent c, DataFlavor[] flavors ) ...{
        
for( DataFlavor flavor : flavors ) ...{
            
if( flavor.equals( DataFlavor.imageFlavor ) ) ...{
                
return true;
            }

        }

        
return false;
    }

    
public boolean importData( JComponent c, Transferable t ) ...{
        
if( canImport(c, t.getTransferDataFlavors() ) ) ...{
            PictureComponent pc 
= ( PictureComponent )c;
            
try ...{
                Image image 
= (Image)t.getTransferData( DataFlavor.imageFlavor );
                pc.setImage( image );
                System.out.println( 
"它能接受" );
                
return true;
            }
 catch( UnsupportedFlavorException e ) ...{
                e.printStackTrace();
            }
 catch( IOException e ) ...{
                e.printStackTrace();
            }

        }

        System.out.println( 
"它不能接受" );
        
return false;
    }

    
public void exportDone( JComponent c, Transferable data, int  action ) ...{
        PictureComponent picture 
= ( PictureComponent )c;
        
if( action == MOVE ) ...{
            picture.setImage( 
null );
        }

    }

    
public int getSourceActions( JComponent c )...{
        
return COPY_OR_MOVE;
    }

    
public Icon getVisualRepresentation( Transferable t ) ...{
        Image image 
= null;
        
try ...{
            System.out.println( 
"getVisualRepresentation" );
            image 
= (Image)t.getTransferData( DataFlavor.imageFlavor );
            
        }
 catch( Exception e ) ...{
            e.printStackTrace();
        }

        
return new ImageIcon( image );
    }

}


效果如下:

2.高级D&D:利用javax.awt.dnd.*中的类实现.
 第二种实现方法和第一种的区别主要是在Drag Source和Drop Target上.而且这第二种实现方法支持所有Component及其子类上实现拖拽,而不止是JComponent.
 
Drag Target   一个对象那个如果想作为拖拽源的话,必须和五个对象建立联系,这五个对象分别是:    * java.awt.dnd.DragSource    获取DragSource的方法很简单,直接调用DragSource.getDefaultDragSource();就可以得到DragSource对象    * java.awt.dnd.DragGestureRecognizer    DragGestureRecognizer类中实现了一些与平台无关的方法,我们如果想在自己的组件上实现拖拽的话只要调用createDefaultDragGestureRecognizer()方法就可以了    该方法接收三个参数,建立组件和拖拽动作之间的关系    * java.awt.dnd.DragGestureListener    当建立了组件和拖拽动作之间的联系后,如果用户执行了拖拽操作,组件将发送一个消息给DragGestureListener监听器    DragGestureListener监听器接下来会发送一个startDrag()消息给拖拽源对象,告诉组件应该执行拖拽的初始化操作了    拖拽源会产生一个DragSourceContext对象来监听动作的状态,这个监听过程是通过监听本地方法DragSourceContextPeer来实现的    * java.awt.datatransfer.Transferable    * java.awt.dnd.DragSourceListener     DragSourceListener接口负责当鼠标拖拽对象经过组件时的可视化处理, DragSourceListener接口的显示结果只是暂时改变组件的外观    同时他提供一个feedback,当用户的拖拽操作完成之后会收到一个dragDropEnd的消息,我们可以在这个函数中执行相应的操作    再来回顾一下拖拽源的建立过程 1.DragGestureRecognizer 确认一个拖拽操作,同时告知 DragGestureListener. 2.假如actions and/or flavors are OK, DragGestureListener 让 DragSource 调用 startDrag(). 3.DragSource建立一个 DragSourceContext和一个DragSourceContextPeer.  4.DragSourceContext 把它自己作为一个DragSourceListener,侦听DragSourceContextPeer.DragSourceContextPeer会从本地系统得到Coponent的状态改变的通知(component entered/exited/is over), 并把他们代理给DragSourceContext.5.DragSourceContext通知 DragSourceListener,而DragSourceListener提供 drag over 的反馈(如果DropTargetListener接受这个动作). 典型的反馈包括让DrogSourceContext改变鼠标.   
6.一旦drop完毕, DragSourceListener就得到一个dragDropEnd的通知消息.
 Drop Source   创建一个 droppable Component必须和下面两个对象发生关联       * java.awt.dnd.DropTarget    DropTarget构造函数使DropTarget 和 DropTargetListener objects发生关联    Droptarget对象提供 setComponent 和addDropTargetListener 两个方法        * java.awt.dnd.DropTargetListener
    DropTargetListener需要与一个Component联系, 以让DropTargetListener在Component操作的时候能够显示”drag under”效果.    
    下面的这个例子以第二种方式实现拖拽:
DragAndDrop.java

package  dnd;
import  java.awt. * ;
import  javax.swing. * ;
import  java.awt.dnd. * ;
import  java.awt.datatransfer. * ;
import  java.io. * ;
import  javax.swing.tree. * ;

public   class  DragAndDrop  extends  JFrame  ... {
    JScrollPane jScrollPane1 
= new JScrollPane();
    JTextArea jTextArea1 
= new JTextArea();
    
    
public DragAndDrop() ...{
        
this.getContentPane().setLayout( new BorderLayout() );
        jScrollPane1.getViewport().setBackground( 
new Color( 10538125 ) );
        jTextArea1.setBackground( Color.orange );
        jTextArea1.setToolTipText( 
"" );
        JTree jtr 
= new JTree();
        jtr.setBackground( Color.BLUE );
        jScrollPane1.getViewport().add( jtr );
        
this.getContentPane().add( jTextArea1, BorderLayout.PAGE_END );
        
this.getContentPane().add( jScrollPane1,  BorderLayout.PAGE_START );
        
        
// Drag And Drop Relative.
        DragSource dragSource = DragSource.getDefaultDragSource();
        dragSource.createDefaultDragGestureRecognizer( jtr, DnDConstants.ACTION_COPY_OR_MOVE, 
new DragAndDropDragGestureListener() );
        DropTarget dropTarget 
= new DropTarget( jTextArea1, new DragAndDropDropTargetListener() );
        
    }

    
public static void main( String[] args ) ...{
        DragAndDrop dad 
= new DragAndDrop();
        dad.setTitle( 
"拖拽演示" );
        dad.setSize( 
400300 );
        dad.setVisible( 
true );
    }

}

DragAndDropDragGestureListener.java

 

package  dnd;

import  java.awt.dnd.DragGestureEvent;
import  java.awt.dnd.DragGestureListener;
import  java.awt.dnd.DragSource;

import  javax.swing.JTree;
import  javax.swing.tree.DefaultMutableTreeNode;
import  javax.swing.tree.TreePath;

/**/ /* Drag Gesture Listener */
public   class  DragAndDropDragGestureListener  implements  DragGestureListener  ... {
    
public void dragGestureRecognized( DragGestureEvent dge ) ...{
        JTree tree 
= (JTree)dge.getComponent();
        TreePath path 
= tree.getSelectionPath();
        
if( path != null ) ...{
            DefaultMutableTreeNode selection 
= ( DefaultMutableTreeNode )path.getLastPathComponent();
            DragAndDropTransferable dragAndDropTransferable 
= new DragAndDropTransferable( selection );
            dge.startDrag( DragSource.DefaultCopyDrop, dragAndDropTransferable, 
new DragAndDropDragSourceListener() );
        }

    }

}

DragAndDropDragSourceListener.java

 

package  dnd;

import  java.awt.dnd.DnDConstants;
import  java.awt.dnd.DragSource;
import  java.awt.dnd.DragSourceContext;
import  java.awt.dnd.DragSourceDragEvent;
import  java.awt.dnd.DragSourceDropEvent;
import  java.awt.dnd.DragSourceEvent;
import  java.awt.dnd.DragSourceListener;

import  javax.swing.JTree;
import  javax.swing.tree.DefaultMutableTreeNode;
import  javax.swing.tree.TreePath;

/**/ /* Drag Source Listener */
public   class  DragAndDropDragSourceListener  implements  DragSourceListener  ... {
    
public void dragDropEnd( DragSourceDropEvent e ) ...{
        
if( e.getDropSuccess() ) ...{
            
int dropAction = e.getDropAction();
            
if( dropAction == DnDConstants.ACTION_MOVE ) ...{
                
//System.out.println( "MOVE: remove node" );
                
            }

        }

    }

    
public void dragEnter( DragSourceDragEvent e ) ...{
        DragSourceContext context 
= e.getDragSourceContext();
        
int dropAction = e.getDropAction();
        
if( ( dropAction & DnDConstants.ACTION_COPY ) != 0 ) ...{
            context.setCursor( DragSource.DefaultCopyDrop );
        }
 else if( ( dropAction & DnDConstants.ACTION_MOVE ) != 0 ) ...{
            context.setCursor( DragSource.DefaultMoveDrop );
        }
 else ...{
            context.setCursor( DragSource.DefaultCopyNoDrop );
        }

    }

    
public void dragExit( DragSourceEvent e ) ...{}
    
public void dragOver( DragSourceDragEvent e  )...{}
    
public void dropActionChanged( DragSourceDragEvent e )...{}
}

DragAndDropDropTargetListener.java

 

package  dnd;
import  java.awt.datatransfer.DataFlavor;
import  java.awt.datatransfer.Transferable;
import  java.awt.datatransfer.UnsupportedFlavorException;
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.io.IOException;

import  javax.swing.JTextArea;

/**/ /* Drop Target Listener */
public   class  DragAndDropDropTargetListener  implements  DropTargetListener  ... {
    
public void dragEnter( DropTargetDragEvent e ) ...{}
    
public void dragOver( DropTargetDragEvent e ) ...{}
    
public void dropActionChanged( DropTargetDragEvent e ) ...{}
    
public void dragExit( DropTargetEvent e ) ...{}
    
public void drop( DropTargetDropEvent e ) ...{
        Transferable t 
= e.getTransferable();
        String s 
= "";
        
try ...{
            
if( t.isDataFlavorSupported( DataFlavor.stringFlavor ) ) ...{
                s 
= t.getTransferData( DataFlavor.stringFlavor  ).toString();
            }

        }
 catch( IOException ioe ) ...{
            ioe.printStackTrace();
        }
 catch( UnsupportedFlavorException ufe ) ...{
            ufe.printStackTrace();
        }

        System.out.println( s );
        DropTarget dt 
= (DropTarget)e.getSource();
        JTextArea d 
= ( JTextArea )dt.getComponent();
        
if( s != null && s.equals( "" ) == false ) ...{
            d.append( s 
+ " ");
        }

    }

}

DragAndDropTransferable.java

 

package  dnd;

import  java.awt.datatransfer.DataFlavor;
import  java.awt.datatransfer.Transferable;
import  java.awt.datatransfer.UnsupportedFlavorException;
import  java.io.IOException;

import  javax.swing.tree.DefaultMutableTreeNode;

/**/ /* Drop Transferable */
public   class  DragAndDropTransferable  implements  Transferable  ... {
    
private DefaultMutableTreeNode treeNode;
    
public DragAndDropTransferable( DefaultMutableTreeNode treeNode ) ...{
        
this.treeNode = treeNode;
    }

    DataFlavor[] flavors 
= ...{ DataFlavor.stringFlavor };
    
public DataFlavor[] getTransferDataFlavors() ...{
        
return flavors;
    }

    
public boolean isDataFlavorSupported( DataFlavor flavor ) ...{
        
for( DataFlavor df : flavors ) ...{
            
if( df.equals( flavor ) ) ...{
                
return true;
            }

        }

        
return false;
    }

    
public Object getTransferData( DataFlavor df ) throws UnsupportedFlavorException, IOException ...{
        
return treeNode;
    }

}


效果如下:



你可能感兴趣的:(Java中的Drag and Drop详解与代码示例 )