Java SWT asyncExec()在拖动时冻结窗口

时间:2014-10-03 07:16:04

标签: java window swt drag freeze

我只需编写SWT线程测试的测试代码,现在卡住了Display.asyncExec()奇怪的行为。

addShellListener(new ShellAdapter() {
        @Override
        public void shellActivated(ShellEvent e) {
            Display.getDefault().asyncExec(new Runnable(){

                @Override
                public void run() {
                    for(int i=0;i<1000;i++)
                    {
                        getLabel().setText(i+"");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }

                }

            });
        }
    });

我只是在shell start上运行带有asyncExec的循环Runnable,它每秒更新shell内的标签值,模拟计时器。一切都很好,滴答作响,直到我试图拖动窗口。窗口冻结拖动(包括&#34;滴答&#34;标签)和通知&#34;程序没有响应&#34;似乎只有Java VM进程终止才能退出。

2 个答案:

答案 0 :(得分:0)

您为Runnable提供的Display.asyncExec在SWT用户界面线程中运行。如果您在此runnable中使用Thread.sleep,则整个用户界面将在睡眠期间被阻止,因此不执行此操作

而不是sleep,你可以使用

Display.getDefault().timerExec(1000, runnable);

安排新的runnable在1000毫秒后运行。

答案 1 :(得分:0)

我不太确定我是否理解用例,但为了每秒更新标签,我建议生成一个后台线程,每秒触发标签更新或使用timerExec()进行更新和为下一次更新()安排另一个timerExec():

timerExec()变体

private class LabelUpdater implements Runnable {
  @Override
  public void run() {
    if( !label.isDisposed() ) {
      label.setText( ... );
      label.getParent().layout();
      display.timerExec( 1000, new LabelUpdater() );
    }
  }
}

shell.addListener( SWT.Activate, new Listener() {
  @Override
  public void handleEvent( Event event ) {
    display.timerExec( 1000, new LabelUpdater() );
  }
} );

后台主题变体

private class LabelUpdater implements Runnable {
  @Override
  public void run() {
    if( !label.isDisposed() ) {
      label.setText( ... );
      label.getParent().layout();
    }
  }
}

Runnable runnable = new Runnable() {
  @Override
  public void run() {
    while( !shell.isDisposed() ) {
      display.asyncExec( new LabelUpdater() );
      try {
        Thread.sleep( 1000 );
      } catch( InterruptedException ignore ) {
        Thread.interrupted();
      }
    }
  }
};
Thread thread = new Thread( runnable );
thread.setDaemon( true );
thread.start();

请注意,shell.isDisposed()检查不是线程安全的,但在实践中并不会造成伤害,因为LabelUpdater必须检查它更新的小部件是否仍然是活着无论如何。 (有关更详细的讨论,请参阅here

相关问题