Вот. Намыл в Swing Hacks
Цитата | Drag a window by clicking on its background using a special event listener.
Most windows let you move them by dragging the titlebar. Some program windows, however, don't have titlebars. In the age of eye-candy interfaces (see iTunes and WinAmp for prime examples) it is very common to have a windowpossibly non-rectangularwithout any titlebar or window controls at all. This makes for a pretty window, but how do you move it? Simply by dragging any available space on the window. Though not terribly intuitive, such programs are commonplace, and this book wouldn't be called Swing Hacks without providing a Java implementation of draggable windows, even when no titlebar is used.
The simplest approach to this problem is to create a listener that simply catches all drags and moves the window:
Код | public class MoveMouseListener implements MouseListener, MouseMotionListener { JComponent target; JFrame frame; public MoveMouseListener(JComponent target, JFrame frame) { this.target = target; this.frame = frame; } public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} public void mouseDragged(MouseEvent e) { frame.setLocation(new Point(e.getX( ),e.getY( )); } }
|
This class implements MouseListener and MouseMotionListener with no-ops for all methods except mouseDragged( ), which moves the frame to the current mouse location. However, this approach has two problems. First, the mouse coordinates are going to be relative to the component, rather than the screen. Thus, a click on a 50 x 50 button in the bottom right of the screen might return (25, 25) when it should really be more like (1000, 700). The other problem is that the code moves the origin of the frame to the mouse cursor. This would look strange because the window would immediately jump so that its upper-left corner is right under the cursor. The proper behavior is for the window to stay in the same position relative to the cursor as the cursor moves around.
The solution to the first problem (getting screen coordinates rather than component coordinates) is to convert mouse coordinates to absolute screen coordinates. The following method does just that (we'll use this shortly in mouseDragged( )):
Код | Point getScreenLocation(MouseEvent e) { Point cursor = e.getPoint( ); Point target_location = this.target.getLocationOnScreen( ); return new Point(
(int)(target_location.getX( )+cursor.getX( )), (int)(target_location.getY( )+cursor.getY( ))); }
|
Solving the second issue (keeping the window static relative to the mouse) requires saving an initial offset between window and cursor, and then maintaining that offset throughout the drag. You should add a new mousePressed( ) implementation that saves the current screen location of the mouse cursor (start_drag) and the current location of the window (start_loc). The distance between the two points can be used to form an offset:
Код | Point start_drag; Point start_loc; public void mousePressed(MouseEvent e) { this.start_drag = this.getScreenLocation(e); this.start_loc = this.getFrame(this.target).getLocation( ); }
|
Next, the listener should maintain the offset difference throughout the drag operation by calculating a new offset each time the mouse moves. Here is the new mouseDragged( ) method:
Код | public void mouseDragged(MouseEvent e) { Point current = this.getScreenLocation(e); Point offset = new Point( (int)current.getX( )-(int)start_drag.getX( ), (int)current.getY( )-(int)start_drag.getY( )); JFrame frame = this.getFrame(target); Point new_location = new Point( (int)(this.start_loc.getX( )+offset.getX( )), (int)(this.start_loc.getY( )+offset.getY( ))); frame.setLocation(new_location); }
|
Using the utility method, it gets the current mouse position in screen coordinates, and then calculates the distance between that position and where the mouse started. Finally, it adds this offset to the starting location for the window to set the window's final location.
Every now and then, the event queue will drop a mouse event. If the code was adding the deltas (change in position) from each drag event, then eventually the user would start to see errors as a result of these dropped events. Because this code always recalculates the window position relative to the start of the drag, these errors don't have an effect. Plus, since Swing sends all mouse events to a dragged componenteven if the cursor moves outside the bounds of the componentyou don't have to worry about the user dragging off the edge of the window and shutting down the whole process.
This method of window dragging has two strengths. First, since the work is done in a listener, you can add this listener to any existing Swing component without subclassing. Any old program can become draggable! Second, only drags on the attached component affect the windowyou can make the background of the window draggable without affecting any of the foreground components (like the Play button on an MP3 player).
|
|