我正在做一项学校作业,要求我能够拿起一块瓷砖,将其拖到某个位置,然后放到那里。我可以使用TransferHandler和dnd包中的一堆东西使它正常工作,但是根据教授的说法,这不是执行此任务的动作的可接受方法。因此,我正在尝试使用MouseListener接口实现相同的效果。

基本设置是这样的:我有一个JPanel派生的类,称为LocationView,其中包含JLabel派生的TileView实例。我需要获取事件,这些事件使我按下鼠标的LocationView和释放鼠标的LocationView。我将鼠标事件通过TileView代理到包含它的LocationView,以便可以正确处理mousePressed事件。

我将System.out.println()添加到了mousePressedmouseReleasedLocationViewTileView鼠标侦听器中,以便可以观察正在生成的事件。令我惊讶的是,在位置A的图块A上按下鼠标,然后拖动到位置B并释放会为图块A和位置A生成鼠标释放事件,但对于位置B都不会。我只需要触发鼠标释放事件位置B。

为了解决此问题,我尝试根据http://weblogs.java.net/blog/2006/09/20/well-behaved-glasspane处的FinalGlassPane实施玻璃窗格。添加玻璃窗格并为其添加事件侦听器之后,我可以看到鼠标事件确实在玻璃窗格中过滤,但是鼠标释放事件仍仅在单击鼠标的项目上被调用。

有没有办法在单独的组件上调用与同一拖动动作相关的mousePressedmouseReleased事件?

编辑:
这是我根据lins314159的回答得出的解决方案

public void mouseReleased(MouseEvent e) {
    Point p = SwingUtilities.convertPoint(LocationView.this, ((Component)e.getSource()).getLocation(), LocationView.this.wsa.getGameView());
    e.translatePoint((int) p.getX(), (int) p.getY());
    Component tile = SwingUtilities.getDeepestComponentAt(LocationView.this.wsa.getGameView(), e.getX(), e.getY());
}

最佳答案

尽管有可能让mouseReleased提供释放鼠标的实际组件作为其来源,但这将带来更多的麻烦,而不是值得的。

以下内容可用于标识释放鼠标的组件。

public void mouseReleased(MouseEvent evt) {
    Point p = ((Component) evt.getSource()).getLocation();
    evt.translatePoint((int) p.getX(), (int) p.getY());
    Component tile = f.getContentPane().getComponentAt(evt.getX(), evt.getY());
}

08-03 19:48