我一直在网上搜索示例或如何使用java的拖放。我找到了一些,但所有示例只允许您拖动到特定位置,即另一个列表框或文本区域。 我想知道是否有办法将物品拖到jpanel或类似的容器上,让物品放在容器上的任何地方。
答案 0 :(得分:2)
只要目标是您要拖动的项目支持的放置目标,就可以将其放到JPanel
等容器中。
您可以控制拖放项目在放置位置的显示方式。如果您的面板覆盖{{1}},那么您可以根据需要绘制该项目。
答案 1 :(得分:2)
'是一种将项目拖入jpanel'
的方法
您可以将DropTarget设置为JPanel。
public class MyDropTarget extends JPanel implements DropTargetListener {
private MyImage image;
private String text;
public MyDropTarget() {
setBackground(new Color(30,60,10));
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, new Color(30,60,10).brighter(), new Color(30,60,10).darker() ) );
DropTarget dt = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true, null);
this.setDropTarget( dt );
}
@Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
if( image != null && image.getImage() != null ) {
g.drawImage( image.getImage(), 0, 0, null );
if(image.isError()){
g.setColor(Color.BLACK);
g.drawString( text, 0, 0 );
}
}
}
public void dragEnter( DropTargetDragEvent dtde ) {
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.RAISED, Color.RED.brighter(), Color.RED.darker() ) );
}
public void dragExit( DropTargetEvent dte ) {
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, UIManager.getColor( "MenuBar.highlight" ), UIManager.getColor( "MenuBar.shadow" ) ) );
}
public void dragOver( DropTargetDragEvent dtde ) {
}
public void drop( DropTargetDropEvent dtde ) {
try {
text = (String) dtde.getTransferable().getTransferData( DataFlavor.stringFlavor );
image = (MyImage)dtde.getTransferable().getTransferData( DataFlavor.imageFlavor );
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, new Color(30,60,10).brighter(), new Color(30,60,10).darker() ) );
dtde.dropComplete( true );
repaint();
} catch( UnsupportedFlavorException e ) {
e.printStackTrace();
} catch( IOException e ) {
e.printStackTrace();
}
this.setDropTarget( null );
}
public void dropActionChanged( DropTargetDragEvent dtde ) {
}
}
答案 2 :(得分:1)
我用这种方式实现了Drag& Drop:
在Java 6中出现了实现Drag& Drop的非常方便的机制,但它确实有它的缺点。例如,您应该明确指定Drop Target,当您需要在Drop Target附近放置对象时,这不是很有用。同样在标准实现中,不保证监听器方法的执行顺序。我将告诉你实现更具扩展性的Drag& Drop的概念。
最初应将鼠标侦听器(Mouse Listener和MouseMotionListener)分配给所有拖动源。需要实现3种方法:鼠标单击对象的方法,在对象上按住鼠标按钮移动鼠标的方法(mouseMragListener中的mouseDragged)和鼠标按下方法。
侦听器分配如下:
component.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//block click right mouse button
if (MouseEvent.BUTTON1 == e.getButton()) {
startDrag(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
//block click right mouse button
if (MouseEvent.BUTTON1 == e.getButton()) {
endDrag(e);
}
}
});
component.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
drag(e);
}
});
因此,当您单击对象Drag& Drop开始时,移动鼠标时应移动对象,当您释放鼠标时,对象应更改其位置并移动到新容器。如果对象将在一个容器的框架中移动,则可以仅实现mouseDragged()方法,其中拖动对象的坐标将被更改:
@Override
public void mouseDragged(MouseEvent e) {
Point mouseLocation = e.getLocationOnScreen();
Component draggedComponent = (Component) e.getSource();
SwingUtilities.convertPointFromScreen(mouseLocation,
draggedComponent.getParent());
draggedComponent.setLocation(mouseLocation);
}
但拖动的对象坐标可以相对于它所在的容器进行设置。因此,当鼠标移动到另一个容器时,需要将一个组件添加到一个新容器并计算新的坐标等。这个方法不是很漂亮和可扩展,所以我建议使用GlassPane来显示拖动的对象。
算法如下:
点击该对象。
获取对象的屏幕截图(请参阅how to make a screenshot)。 隐藏原始对象。
在glassPane上绘制对象的屏幕截图,基于 鼠标的坐标。
移动鼠标时,需要重新绘制屏幕截图 到新的坐标。
释放鼠标时,需要将对象放在 光标所在的容器。
显示原始对象。
使用这种方法,我们对放置光标的容器没有任何依赖关系,因此可以在任何地方“丢弃”对象。
具有透明效果的GlassPane:
public class GhostGlassPane extends JPanel {
private final AlphaComposite composite;
private BufferedImage ghostImage = null;
private Point location = new Point(0, 0);
public GhostGlassPane() {
setOpaque(false);
composite = AlphaComposite.getInstance(AlphaComposite.
SRC_OVER, 0.7f);
}
public void paintComponent(Graphics g) {
if (ghostImage == null)
return;
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(composite);
g2.drawImage(ghostImage, (int) (location.getX()),
(int) (location.getY()), null);
}
}
在此回复中,仅给出了实施的概念。
此信息取自我的文章:Frequently Asked Questions during Java applet development