tags:

views:

109

answers:

1

I am working on a school assignment that requires me to be able to pick up a tile, drag it to a location, then drop it there. I was able to get this working using TransferHandler and a bunch of stuff from the dnd package, but this is not an acceptable way to perform this action for this assignment according to the professor. So, I am trying to achieve the same effect using the MouseListener interface.

The basic setup is this: I have a JPanel-derived class called LocationView that contains JLabel-dervived instances of TileView. I need to get events that give me the LocationView that has the mouse pressed on and the LocationView that has the mouse released on. I am proxying mouse events through the TileView to its containing LocationView so that I can properly handle the mousePressed event.

I added System.out.println()'s to the mouse listeners for mousePressed and mouseReleased to both LocationView and TileView so that I could observe the events that were being generated. To my surprise, pressing the mouse on Tile A in Location A, then dragging to Location B and releasing would generate a mouse released event for both Tile A and Location A, but not for Location B. I need the mouse released event triggered for only Location B.

To try to work around this, I tried implementing a glass pane based off of the FinalGlassPane found at http://weblogs.java.net/blog/2006/09/20/well-behaved-glasspane. After adding the glass pane and adding an event listener for it, I can see that the mouse events are indeed filtering through the glass pane, but the mouse released event is still only being called on the item the mouse was clicked on.

Is there a way to have mousePressed and mouseReleased events associated with the same drag action be called on separate components?

EDIT: Here is the solution that I arrived at, based off of the answer by 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());
}
+1  A: 

While it's likely possible to have mouseReleased give the actual component the mouse was released on as its source, it would be more trouble than it's worth.

The following can be used to identify the component that the mouse was released on.

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());
}
lins314159
This translation of the source location does not seem to be working in my circumstance. When I click on a tile, I get the location of the source as 1,1, which is then translated respective to the tile that I am in. This means that the coordinate that is produced is not correct, leading to the wrong component being selected.
Chris Lieb
I tweaked your code a bit to finally get it to work. The tweaks were needed due to the number of nested components that I had. The solution is posted as an edit on the original question.
Chris Lieb