Java中的Drag and Drop详解…

xiaoxiao2021-02-28  119

博主写得很详细,最近正在为这个头疼,看了这个终于搞清楚了 原文地址:Java中的Drag and Drop详解与代码示例 作者:SuRen 对对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; 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; 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; 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; 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; 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; 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;     } }
转载请注明原文地址: https://www.6miu.com/read-31388.html

最新回复(0)