我最近对对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.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
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( 2, 2 ) );
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( 20, 20, 20, 20 ) );
mainFrame.getContentPane().add( mainPanel );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.setSize( 350, 400 );
mainFrame.setLocationRelativeTo( null );
mainFrame.setVisible( true );
}
}
PicrureComponent.java
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(125, 125 ) );
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( 0, 0