问题描述
我是一名经验丰富的 Java 开发人员,但我是用户界面开发的新手,我一直在使用 Java AWT 开发应用程序。我想在用户界面中添加拖动功能。
令我惊讶的是,java.awt.Shape
不是 java.awt.Component
,因此我没有看到将可拖动钩子添加到我的特定形状的“一流”方式。相反,我利用应用程序窗口的鼠标事件挂钩,然后在处理任何拖动之前简单地检测鼠标光标何时位于感兴趣的形状上。
由于我的应用程序不需要 Z 轴层的复杂性,我限制任何拖动的形状与另一个可拖动的形状相交。如果用户将一个拖到另一个上,它只会“碰撞”并保持在那里。然后用户首先将其从碰撞中拖出,然后将其放置在其他地方。您会注意到,在我为 Stackoverflow 留下评论的paint() 方法中检测到了交集。
用户界面有效。除此之外,很容易产生一种竞争条件,如果我非常快速地拖动形状,它可能会深深地嵌套在另一个形状中并卡住。
问题:我是否以完全错误的方式处理这个问题?是否有一种优雅的最佳实践可以在进一步事件发生之前“及时”检测碰撞?
package test;
import java.awt.Basicstroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.ScrollPane;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.RoundRectangle2D;
/**
* Simple graphical application with two white rectangles that can be dragged around the application window
* */
final class DraggableTest extends Component implements MouseListener,MouseMotionListener {
public static void main( String[] args ) {
Frame window = new Frame( "Test Dragging Things" );
ScrollPane scrollPane = new ScrollPane();
DraggableTest app = new Draggabletest();
scrollPane.add( app );
window.add( scrollPane );
app.setSize( new Dimension( 400,400 ) );
app.setPreferredSize( new Dimension( 400,400 ) );
window.setSize( 200,200 );
window.setVisible( true );
window.addWindowListener( new WindowAdapter() {
@Override
public void windowClosing( WindowEvent e ) {
window.dispose();
}
} );
app.addMouseMotionListener( app );
app.addMouseListener( app );
}
private static final long serialVersionUID = 2673458042104218875L;
@Override
public void paint( Graphics g ) {
Graphics2D g2 = ( Graphics2D ) g;
// redraw the draggable shapes in their last dragged position
draggableShape1 = new RoundRectangle2D.Double( lastDragged1.x,lastDragged1.y,40,20,10,10 );
g2.setPaint( Color.WHITE );
g2.fill( draggableShape1 );
g2.setPaint( Color.BLACK );
g2.setstroke( new Basicstroke() );
g2.draw( draggableShape1 );
draggableShape2 = new RoundRectangle2D.Double( lastDragged2.x,lastDragged2.y,10 );
g2.setPaint( Color.WHITE );
g2.fill( draggableShape2 );
g2.setPaint( Color.BLACK );
g2.setstroke( new Basicstroke( 2.0f,Basicstroke.CAP_BUTT,Basicstroke.JOIN_MITER,20.0f,new float[] { 10.0f / 2.0f },0.0f ) );
g2.draw( draggableShape2 );
// HERE IS WHERE MY STACKOVERFLOW QUESTION LIES
// Cancel any drag operation if a dragged object begins to intersect another.
// Because then we would have a requirement for differentiating and specifying which object to drag.
synchronized (this) {
if ( draggableShape1.getBounds2D().intersects( draggableShape2.getBounds2D() ) ) {
dragging1 = false;
dragging2 = false;
Toolkit.getDefaultToolkit().beep(); // alert the user to termination of the drag
}
}
}
// Two shapes drawn in method paint()
private Shape draggableShape1 = null;
private Shape draggableShape2 = null;
// initial locations of draggable shapes
private Point initialPosition1 = new Point( 0,0 );
private Point initialPosition2 = new Point( 100,100 );
// position shape last dropped to
private Point lastDragged1 = initialPosition1;
private Point lastDragged2 = initialPosition2;
// is the shape being dragged Now?
boolean dragging1 = false;
boolean dragging2 = false;
// During drag,offset between mouse click position and the object being dragged
int dragMouSEOffsetX = 0;
int dragMouSEOffsetY = 0;
// Drag event sequence:
// Mouse button down.
// Mouse dragged to 1204,452
// (repaint called from method mouseDragged )
// Mouse button released.
@Override
public void mousepressed(MouseEvent e) {
System.err.println( "Mouse button down." );
Point mouseDownPosition = e.getPoint();
// if mouse down in a draggable shape,assume we are starting a drag
if ( draggableShape1.contains( e.getPoint() ) ) {
dragging1 = true;
// Detect the offset between the mouse position and the shape's top left point
dragMouSEOffsetX = draggableShape1.getBounds().x - mouseDownPosition.x; // negative is left
dragMouSEOffsetY = draggableShape1.getBounds().y - mouseDownPosition.y; // negative is up
}
if ( draggableShape2.contains( e.getPoint() ) ) {
dragging2 = true;
// Detect the offset between the mouse position and the shape's top left point
dragMouSEOffsetX = draggableShape2.getBounds().x - mouseDownPosition.x; // negative is left
dragMouSEOffsetY = draggableShape2.getBounds().y - mouseDownPosition.y; // negative is up
}
}
/**
* The mouse button is down and is being moved.
* This has an effect IFF one of the draggable items was under the pointer when the button was pressed
* */
@Override
public void mouseDragged( MouseEvent e ) {
Point mouseDragPosition = e.getPoint();
if ( dragging1 || dragging2 ) {
System.err.println( "Mouse dragged to " + mouseDragPosition.x + "," + mouseDragPosition.y );
System.err.println( "Shape dragged to " + ( mouseDragPosition.x + dragMouSEOffsetX ) + "," + ( mouseDragPosition.y + dragMouSEOffsetY ) );
}
if ( dragging1 ) { // if we prevIoUsly clicked on the shape
if ( ! mouseDragPosition.equals( lastDragged1 ) ) { // Ignore drag of less than one pixel (measured in granularity of int)
Point newDragPoint = new Point( mouseDragPosition.x + dragMouSEOffsetX,mouseDragPosition.y + dragMouSEOffsetY );
lastDragged1 = newDragPoint;
repaint();
}
}
if ( dragging2 ) { // if we prevIoUsly clicked on the shape
if ( ! mouseDragPosition.equals( lastDragged2 ) ) { // Ignore drag of less than one pixel (measured in granularity of int)
lastDragged2 = new Point( mouseDragPosition.x + dragMouSEOffsetX,mouseDragPosition.y + dragMouSEOffsetY );
repaint();
}
}
}
/**
* Any time the mouse button comes up,any dragging state is concluded
* */
@Override
public void mouseReleased(MouseEvent e) {
System.err.println( "Mouse button released." );
dragging1 = false;
dragging2 = false;
}
@Override
public void mouseMoved( MouseEvent e ) {
// nothing to do
}
/**
* The mouse enters or re-enters the application window
* */
@Override
public void mouseEntered(MouseEvent e) {
System.err.println( "Mouse entered." );
}
/**
* The mouse leaves the application window
* */
@Override
public void mouseExited(MouseEvent e) {
System.err.println( "Mouse left." );
}
/**
* A combination of mouse down and mouse up has been detected as a click.
* Not implemented.
* */
@Override
public void mouseClicked(MouseEvent e) {
// Event sequence:
// Mouse button down.
// Mouse button released.
// Click.
System.err.println( "Click." );
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)