我有两个组件,每个组件都有自己的MouseMotionListener。当我在拖动第一个组件的同时将鼠标从第一个组件移动到第二个组件时,似乎为第二个组件禁用了MouseMotionListener,即尽管我将鼠标移到第二个组件上,也根本没有调用mouseMoved。我如何避免这种“禁用”?
例:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DragTest implements MouseMotionListener {
private static JPanel p1 = new JPanel();
private static JPanel p2 = new JPanel();
public DragTest() {
}
public static void main(String[] args) {
p1.setBackground(Color.RED);
p1.addMouseMotionListener(new DragTest());
p2.setBackground(Color.BLUE);
p2.addMouseMotionListener(new DragTest());
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(100, 100, 600, 300);
frame.setLayout(new GridLayout(1, 2));
frame.add(p1);
frame.add(p2);
frame.setVisible(true);
}
@Override
public void mouseMoved(MouseEvent e) {
if (e.getSource() == p1) {
System.out.println("mouse movement in p1");
} else if (e.getSource() == p2) {
System.out.println("mouse movement in p2");
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (e.getSource() == p1) {
System.out.println("mouse drag in p1");
} else if (e.getSource() == p2) {
System.out.println("mouse drag in p2");
}
}
}
最佳答案
免责声明:这是核心拖放API的一个非常非常基础的示例,它基于this example,this example和this example,旨在简单地演示确定规定的放置位置的可能性
因此,当涉及到事物拖动时,尤其是跨组件时,通常最好使用拖放API,而不是简单地使用MouseMotionListener
和MouseListener
。这就是API的设计目的,并向两个目标提供有关操作性质的通知
以下示例仅存储您放置物体的位置并在此处绘制一个漂亮的小点
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
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.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
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 java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;
public class DragAndDropTest {
public static void main(String[] args) {
new DragAndDropTest();
}
public DragAndDropTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(1, 2));
add(new DropPane());
add(new DragPane());
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class DragPane extends JPanel {
private DragSource ds;
private Transferable transferable;
public DragPane() {
ds = new DragSource();
transferable = new Transferable() {
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{DataFlavor.stringFlavor};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return DataFlavor.stringFlavor.equals(flavor);
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return "This is a test";
}
};
ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, new DragGestureListener() {
@Override
public void dragGestureRecognized(DragGestureEvent dge) {
// This is where you would export the data you want
// to transfer
ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, new DragSourceListener() {
@Override
public void dragEnter(DragSourceDragEvent dsde) {
}
@Override
public void dragOver(DragSourceDragEvent dsde) {
}
@Override
public void dropActionChanged(DragSourceDragEvent dsde) {
}
@Override
public void dragExit(DragSourceEvent dse) {
}
@Override
public void dragDropEnd(DragSourceDropEvent dsde) {
}
});
}
});
setLayout(new GridBagLayout());
add(new JLabel("Drag from here"));
setBorder(new LineBorder(Color.RED));
}
}
public class DropPane extends JPanel {
private List<Point> dropPoints;
public DropPane() {
dropPoints = new ArrayList<>(25);
setDropTarget(new DropTarget(this, new DropTargetListener() {
@Override
public void dragEnter(DropTargetDragEvent dtde) {
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
@Override
public void dragExit(DropTargetEvent dte) {
}
@Override
public void drop(DropTargetDropEvent dtde) {
// Normally here, I'd inspect the Transferable and make sure
// what is been dropped and can be imported, I'd then go through
// the process of unwrapping the data from the Transferable and
// processing it appropriatly, but in this example, I really don't
// care, I just care about WHERE the event occured
dropPoints.add(dtde.getLocation());
dtde.dropComplete(true);
repaint();
}
}));
setLayout(new GridBagLayout());
add(new JLabel("Drop to here"));
setBorder(new MatteBorder(1, 1, 1, 0, Color.RED));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
for (Point p : dropPoints) {
g.fillOval(p.x - 2, p.y - 2, 5, 5);
}
}
}
}