2012-03-15 62 views
2

之间的事件后调用我试图仿效使用下面的代码在Swing单击事件:允许事件在Swing

event = new MouseEvent(target, MouseEvent.MOUSE_PRESSED, ...) 
java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event); 
event = new MouseEvent(target, MouseEvent.MOUSE_RELEASED, ...) 
java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event); 
event = new MouseEvent(target, MouseEvent.MOUSE_CLICKED, ...) 
java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event); 

这适用于大多数的部件,但问题是,如果组件产生它是自己的事件,例如,如果组件接收MOUSE_PRESSED,它会生成一些事件并使用dispatchEvent(newEvent)提交它们;与正常的单击事件顺序应该是:

MOUSE_PRESSED 
newEvent 
MOUSE_RELEASED 
MOUSE_CLICKED 

但是因为我的代码顺序是:

MOUSE_PRESSED  
MOUSE_RELEASED 
MOUSE_CLICKED 
newEvent 

而且它打破了应用程序逻辑。我可以通过在我的postEvent()调用之间添加Thread.sleep()调用来轻松修复它,但我不想这样做,因为此方法被称为很多,我不希望它变慢,特别是因为当前代码在95%的情况下起作用。

我将如何模拟事件序列,从而允许在它们之间创建新事件?我无法访问组件代码,所以我只能修改我的仿真方法。

回答

3

你可以把你自己的事件队列这将使你的事件进行全面控制。例如:

class SchedulingEventQueue extends EventQueue 
    { 
     // Use Map< AWTEvent, List<AWTEvent> > to support multiple events 
     private final Map< AWTEvent, AWTEvent > eventSchedule = new HashMap< AWTEvent, AWTEvent >(); 

     public void scheduleEvent(final AWTEvent event, final AWTEvent dependentEvent) 
     { 
     eventSchedule.put(dependentEvent, event); 
     } 

     @Override 
     protected void dispatchEvent(final AWTEvent event) 
     { 
     try 
     { 
      super.dispatchEvent(event); 
     } 
     finally 
     { 
      // Dispatch any dependent event 
      AWTEvent scheduledEvent = eventSchedule.remove(event); 
      if(scheduledEvent != null) 
      { 
      postEvent(scheduledEvent); 
      } 
     } 
     } 
    } 

    // Now the code to post the events becomes: 
    { 
     SchedulingEventQueue eventQueue = new SchedulingEventQueue(); 

     Toolkit.getDefaultToolkit().getSystemEventQueue().push(eventQueue); 

     MouseEvent pressEvent = new MouseEvent(target, MouseEvent.MOUSE_PRESSED, ...) 
     MouseEvent releaseEvent = new MouseEvent(target, MouseEvent.MOUSE_RELEASED, ...) 
     MouseEvent clickEvent = new MouseEvent(target, MouseEvent.MOUSE_CLICKED, ...) 

     eventQueue.scheduleEvent(clickEvent, releaseEvent); 
     eventQueue.scheduleEvent(releaseEvent, pressEvent); 
     eventQueue.postEvent(pressEvent); 
    } 

你刚才链中的事件一起,使它们不会发布直到前一事件已派出允许由组件产生的任何中间事件分派期间发布之前,你的下一个事件发布。我没有尝试过,但它应该可以工作。

+0

或者,您可以实施postEvents(列表< AWTEvent >事件),并在内部处理调度,以防止调用代码必须以正确的顺序获取scheduleEvent()和postEvent()调用。您可以按相反顺序遍历列表,调度每个列表,然后发布第一个事件。 – nicktalbot 2012-03-15 16:56:41

+0

这很好,很少问题:1)getSystemEventQueue()。push(eventQueue),我应该每次模拟鼠标点击时调用它,还是推动一次并重复使用?当我不再需要它时,我没有看到任何方法从系统中删除我的eventQueue 2)我试图修改它以检查它何时完成处理事件,http://pastebin.com/h6zFMfH3,工作正常事件创建一个模块对话框,它阻止dispatchEvent,我如何检查当前事件被阻止?再次感谢! – 2012-03-15 17:23:06

+0

您只需要推送一次事件队列,然后仅为每组事件重用单个SchedulingEventQueue实例。 – nicktalbot 2012-03-15 17:42:39

3

您可以使用e.consume()事件从鼠标/键盘事件,和/或替换/生成自己连(S)到EventQueue