我们目前正在为一个必须在下周完成的项目进行修复,所以我们有点时间用完了(别担心,我想说的是我们没有时间抛弃它们我们所有的代码,重新开始......)。
我们有一个JPanel
(=“page”),其上有一堆其他JPanels
(充当图表的节点)。用户可以通过单击第一个节点然后在第二个节点上进行连接或通过将一条线从一条线拖到另一条节点来连接节点。
但最后一个没有像我们预期的那样工作:
如果我们将连接线拖出它启动的节点(例如,到页面或任何其他节点),我们用来创建该行的mouseDragged
事件不会以{{1}结束}}。如果我将鼠标放在我开始拖动的节点上,它就可以正常工作,但是我无法与之建立任何连接。
为了能够绘制与页面的连接,我们将调度事件,直到它们到达将要处理它们的页面。
有趣的是:一切都有效,除非我们在mouseRelease
的代码中添加了System.out.println("mouse dragged");
,否则我们会有一连串的“鼠标拖动”输出。
连接本身适用于。
所以,我的问题是:如果mouseDragged()
发生在最初启动mouseDragged
的组件之外,我该如何结束mouseReleased
事件?
有没有办法中止mouseDragged
事件?
是否有可能/必须“伪造”中断mouseDragged
事件?
希望有一种解决方案不会让厨师多煮咖啡....
问候, FLO
编辑: 好的,给你一些代码:
由节点和页面实现的接口使事情变得更容易:
mouseRelease
事件的适配器
import java.awt.event.MouseEvent;
/**
* Interface which can be used together with MouseEventListenerAdapter to
* easily receive mouse events.
*
* @author flo
*/
public interface MouseEventsInterface {
/**
* Called when a mouse clicked event is received.
*
* @param e Triggered mouse event.
*/
void onMouseClicked(MouseEvent e);
/**
* Called when a mouse dragged event is received.
*
* @param e Triggered mouse event.
*/
void onMouseDragged(MouseEvent e);
[and so on...]
/**
* Called when a mouse released event is received.
*
* @param e Triggered mouse event.
*/
void onMouseReleased(MouseEvent e);
}
我们如何调度事件,如果事件来自节点内的另一个面板,则使用第一部分。 NodeConnectorMouseEvent是一个常规的MouseEvent,能够存储它已被分配的所有组件......
/**
* Class which forwards mouse events to a MouseEventsInterface which have
* originally been targeted to a MouseInputAdapter.
*
* @author flo
*
* @param <M> The interface to which events are sent.
*/
public class MouseEventListenerAdapter<M extends MouseEventsInterface> extends MouseInputAdapter {
/**
* Interface which receives the events which are forwarded by this class.
*/
private M mei;
/**
* Creates an adapter which forwards all events to the MouseEventsInterface.
*
* @param mei The receiver of the forwarded events.
*/
public MouseEventListenerAdapter(final M mei) {
this.mei = mei;
}
@Override
public final void mousePressed(final MouseEvent e) {
this.mei.onMousePressed(e);
}
@Override
public final void mouseClicked(final MouseEvent e) {
this.mei.onMouseClicked(e);
}
@Override
public final void mouseDragged(final MouseEvent e) {
this.mei.onMouseDragged(e);
}
@Override
public final void mouseMoved(final MouseEvent e) {
this.mei.onMouseMoved(e);
}
@Override
public final void mouseReleased(final MouseEvent e) {
this.mei.onMouseReleased(e);
}
/**
* Returns the receiver of the forwarded {@link MouseEvent MouseEvents}.
* @return the receiver of the forwarded {@link MouseEvent MouseEvents}.
*/
protected final M getEventReceiver() {
return this.mei;
}
}
页面的一些代码:
/**
* Dispatch mouse event.
*
* @param e the e
*/
private void dispatchMouseEvent(final MouseEvent e) {
if (e instanceof NodeConnectorMouseEvent) {
((NodeConnectorMouseEvent) e).addDispatchingComponent(this);
} else {
// f.e. moved over IOPort, PortPanel
e.setSource(this);
}
this.getParent().dispatchEvent(e);
}
还有很多,但我想这是有趣的部分。 谢谢你的帮助!
答案 0 :(得分:2)
我不确定我理解你的方法,但有两件事情浮现在脑海中:
您可以consume()
一个“事件,以便它不会以默认方式处理它的来源。”
您可以push()
使用自己的EventQueue
并覆盖dispatchEvent()
来修改前往最终目的地的任何事件。有一个相关示例here,Global Event Dispatching是一个很好的指南。
附录:虽然不适用于当前问题,但还有其他方法可以选择多个节点:
GraphPanel
使用鼠标拖动或按住Shift键单击进行多项选择,并使用右键单击查看上下文菜单。
JGraph
使用shift-click进行多项选择; com.mxgraph.examples.swing.GraphEditor
就是一个例子。
此example建议如何使用JInternalFrame
。
答案 1 :(得分:0)
我想知道的一些事情: 1.在页面的代码中,你有lastDragPosition = new Point(0,0);为什么? 2.为什么不直接使用mouseExited(MouseEvent e)方法来模拟拖动中断并只运行一个线程来检查是否已经拖动,如果已经完成了拖动,则连接点< / p>
答案 2 :(得分:0)
从我注意到,当执行拖动时,MouseEvent
不再被分派给听众。相反,您可以使用DragSourceListener
,它有几种有用的方法。您感兴趣的那个可能是dragDropEnd
,当拖动操作结束时,无论是否成功都会调用它。