允许事件在Swing中的postEvent调用之间在EvenQueue中发布

时间:2012-03-15 15:01:15

标签: java swing events

我正在尝试使用以下代码模拟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%的情况下有效。

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

2 个答案:

答案 0 :(得分:3)

您可以使用e.consume()来处理来自鼠标/键盘事件的事件,和/或将自己的偶数替换/生成EventQueue

答案 1 :(得分: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 );
    }

您只需将事件链接在一起,以便在调度上一个事件之前不会发布它们,从而允许在发布下一个事件之前在发送期间发布组件创建的任何中间事件。我没试过,但它应该有用。