Java 在画布SWT Draw2D中拖动图形
我已经编写了允许拖放到画布上的代码,并支持在画布本身中拖动拖放的图形。问题在于,在画布中实现拖动的代码偶尔会抛出NullPointerException。我试图孤立这起触发事件,但徒劳。就方法论而言,我也看不出有什么不对劲。我知道这是一个很长的机会,但有人能告诉我正确的方向来解决这个问题吗?非常感谢。我添加了简短的可测试代码,但NPE只是偶尔抛出Java 在画布SWT Draw2D中拖动图形,java,user-interface,canvas,swt,draw2d,Java,User Interface,Canvas,Swt,Draw2d,我已经编写了允许拖放到画布上的代码,并支持在画布本身中拖动拖放的图形。问题在于,在画布中实现拖动的代码偶尔会抛出NullPointerException。我试图孤立这起触发事件,但徒劳。就方法论而言,我也看不出有什么不对劲。我知道这是一个很长的机会,但有人能告诉我正确的方向来解决这个问题吗?非常感谢。我添加了简短的可测试代码,但NPE只是偶尔抛出 public class RepeatDrop { private Shell shell; private Displ
public class RepeatDrop
{
private Shell shell;
private Display display;
private final Label lblUnicorn;
private final Canvas canvas;
public static void main(String args[])
{
new RepeatDrop();
}
public RepeatDrop()
{
display = new Display();
shell = new Shell(display);
shell.setText("SWT Application");
shell.setLayout(new GridLayout(2, false));
Group grpPalette = new Group(shell, SWT.NONE);
grpPalette.setText("Palette");
grpPalette.setLayout(new GridLayout());
grpPalette.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, true));
lblUnicorn = new Label(grpPalette, SWT.BORDER | SWT.HORIZONTAL | SWT.CENTER);
lblUnicorn.setText("UNICORN");
// ADDED A FINAL HERE!!
lblUnicorn.setAlignment(SWT.CENTER);
final Group grpCanvas = new Group(shell, SWT.NONE);
grpCanvas.setText("Canvas");
grpCanvas.setLayout(new GridLayout());
grpCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
canvas = new Canvas(grpCanvas, SWT.NONE);
canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
LightweightSystem lws = new LightweightSystem(canvas); //
final IFigure panel = new Figure(); //
lws.setContents(panel); //
DragSource dragSource1 = new DragSource(lblUnicorn, DND.DROP_COPY);
Transfer[] transfers1 = new Transfer[] { TextTransfer.getInstance() };
dragSource1.setTransfer(transfers1);
dragSource1.addDragListener(new DragSourceListener()
{
public void dragStart(DragSourceEvent event)
{
if (lblUnicorn.getText().length() == 0)
{
event.doit = false;
}
}
public void dragSetData(DragSourceEvent event)
{
if (TextTransfer.getInstance().isSupportedType(event.dataType))
{
event.data = lblUnicorn.getText();
}
}
public void dragFinished(DragSourceEvent event)
{
}
});
Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
DropTarget dropTarget = new DropTarget(canvas, DND.DROP_COPY | DND.DROP_DEFAULT);
dropTarget.setTransfer(types);
dropTarget.addDropListener(new DropTargetListener()
{
public void dragEnter(DropTargetEvent event)
{
if (event.detail == DND.DROP_DEFAULT)
{
if ((event.operations & DND.DROP_COPY) != 0)
{
event.detail = DND.DROP_COPY;
}
else
{
event.detail = DND.DROP_NONE;
}
}
}
public void dragLeave(DropTargetEvent event)
{
}
public void dragOperationChanged(DropTargetEvent event)
{
}
public void dragOver(DropTargetEvent event)
{
}
public void drop(DropTargetEvent event)
{
}
public void dropAccept(final DropTargetEvent event)
{
if (TextTransfer.getInstance().isSupportedType(event.currentDataType))
{
String d = (String) TextTransfer.getInstance().nativeToJava(event.currentDataType);
org.eclipse.swt.graphics.Point droppoint = canvas.toControl(event.x, event.y);
// DRAW 2D SECTION
RectangleFigure node1 = new RectangleFigure();
Rectangle rect = new Rectangle(droppoint.x, droppoint.y, 20, 20);
Rectangle rect2 = new Rectangle(droppoint.x, droppoint.y, 100, 25);
node1.setBounds(rect);
node1.setBackgroundColor(ColorConstants.cyan);
org.eclipse.draw2d.Label droppedName = new org.eclipse.draw2d.Label(d);
droppedName.setLocation(new Point(droppoint.x, droppoint.y)); // draw2d.
// point
droppedName.setBounds(rect2);
node1.add(droppedName);
panel.add(node1);
panel.add(droppedName);
new Dragger(node1);
new Dragger(droppedName);
canvas.redraw();
}
}
});
shell.pack();
shell.setSize(400, 300);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
}
static class Dragger extends MouseMotionListener.Stub implements MouseListener
{
public Dragger(IFigure figure)
{
figure.addMouseMotionListener(this);
figure.addMouseListener(this);
}
Point last;
public void mouseReleased(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseDoubleClicked(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
last = e.getLocation();
}
public void mouseDragged(MouseEvent e)
{
Point p = e.getLocation();
Dimension delta = p.getDifference(last);
{
last = p;
Figure f = ((Figure) e.getSource());
f.setBounds(f.getBounds().getTranslated(delta.width, delta.height));
}
}
}
}
好的,首先,我找到了一个可复制的程序来获得NPE:
A
和B
)拖到画布上B
上拖动A
,而不释放鼠标按钮mouseDragged()
方法中的last
。此变量首先在mousePressed()
中设置。现在这通常是可以的,但是当你把A
拖到B
上时,焦点会从A
变为B
。但是,由于您没有实际单击B
mouseDragged()
会被激发,尽管mousedpressed()
没有引起NPE
现在有一种简单的方法可以通过初始化构造函数中的last
来解决此问题:
public Dragger(IFigure figure)
{
figure.addMouseMotionListener(this);
figure.addMouseListener(this);
Rectangle bounds = figure.getBounds();
last = new Point(bounds.x, bounds.y);
}
非常感谢你!但你所说的焦点改变是什么意思?在这个修复之前,我也有过这样的例子,画布上只有一个元素,试图拖动它时抛出了一个NPE。@Asher,你总是有矩形和文本,对吗?这已经是两位数了。至于焦点的改变:你没有注意到当你把一个图形拖到另一个图形上时,另一个图形反而被拖走了吗?@Asher焦点的改变是另一个问题。请随意发布一个关于它的新问题。我记得在过去曾经处理过这个问题,今天我可能会把它挖出来。