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

 2022-01-07 

Allow events to be posted in EvenQueue between postEvent calls in Swing

我正在尝试使用以下代码在 Swing 中模拟点击事件:

1
2
3
4
5
6
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); 提交它们;使用正常的点击事件顺序将是:

1
2
3
4
MOUSE_PRESSED
newEvent
MOUSE_RELEASED
MOUSE_CLICKED

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

1
2
3
4
MOUSE_PRESSED    
MOUSE_RELEASED
MOUSE_CLICKED
newEvent

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

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


您可以推送自己的事件队列,这将使您完全控制事件。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    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 );
    }

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


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