InvokeLater按事件排序

use*_*011 8 java swing awt event-dispatch-thread

EventQueuejavadoc的规定,则要求入队的事件顺序,为了调度.

难道纠正Runnableš排队,以EventQueue.invokeLater保证后续的用户事件(例如,之前被分派MouseEvent)?换句话说Runnable,如果用户事件发生之后,可以在排队之前执行事件处理程序EventQueue.invokeLater.

谢谢!

Tom*_*ine 9

API文档声明事件是

按照他们入队的顺序排列.

但是如果你检查源代码,你会发现情况并非总是如此,尽管它在大多数情况下都是正确的.


Cli*_*iff 5

可能最好解释一下你想要做什么.通常,事件调度系统的设计使您不应该知道或担心其内部.如果您正在编写直接更新UI的事件处理程序,那么不使用Runnable并在线执行更新可能是有意义的.但是,如果您的事件处理程序执行一些花费不确定时间的计算或处理,那么您可能希望使用一个线程,该线程最终将使用带有Swing.invokeLater调用的Runnable执行UI更新.需要在发送事件时了解事件的顺序意味着您试图在逻辑中构建可能属于其他地方的假设.

例如,考虑一个鼠标单击事件处理程序,它在一个线程中执行繁重的处理(网络下载或DBMS查询),然后更新UI中的文本标签.您可能希望确保在用户单击UI上的其他位置之前进行处理和UI更新,以避免处理点击的模糊性.在这种情况下,您可能会在初始鼠标单击事件中立即禁用UI或UI的某些可单击部分,以便UI保持响应,但保护您的onMouse处理程序不会重新进入,直到完全处理原始单击事件.(请原谅以下片段,因为自从我完成Swing以来已经有好几年了,它更像是伪代码.)

void setUIEnabled(boolean enable) {
   for(Button eachUIButton : getAllClickableButtons()) {
      eachUIButton.setEnabled(enable);
   }
}

void onMouseClick(MouseEvent event) {
   setUIEnabled(false);
   new Thread(
      new Runnable() {
         public void run() {
            final String result = doLengthyProcessing();
            enableRunnable = new Runnable() {
               public void run() {
                  setUIEnabled(true);
                  updateTextLabelFromLengthyProcess(result);
               }
            };
            Swing.invokeLater(enableRunnable);
         }
      }
   ).start();
}
Run Code Online (Sandbox Code Playgroud)

这里的想法是你编写逻辑,使它不依赖于调度事件的随机顺序,而是确认处理可能比下一个传入的鼠标事件花费更长的时间,并为这样的时间做出规定.一个微妙的改进是绘制一个进度指示器或进度微调器,以指示正在为用户完成工作.

  • 再次,让我更清楚一点。事件处理程序应在产生后台线程之前立即禁用 UI。后台线程不应关心何时处理 Swing 事件,因为 UI 已被事件处理程序禁用。它只是做它必须做的事情,然后发布一个可运行的东西,当它完成时重新启用 UI。 (2认同)