SWT Modal ProgressBar松散窗口焦点

时间:2014-08-26 15:18:50

标签: java swt

我有一个模态对话框,用线程制作任务。 这很好用,除了主窗口不再可聚焦,在操作系统任务栏中点击我的应用程序图标没有效果,这种类型的事件被冻结,当其他窗口结束并且我想显示时它是一个问题再一次。

(我只使用SWT,没有JFace)

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;

public class ProgressBox extends Dialog {

    protected Shell dialog;
    protected ProgressBar bar;

    public ProgressBox(Shell parent, final String name) {
        super(parent);
        dialog = new Shell(parent, SWT.APPLICATION_MODAL | SWT.TITLE); 
        dialog.setSize(400,64);
        dialog.setText(name);
        dialog.setLayout(new FillLayout());
        bar = new ProgressBar(dialog, SWT.SMOOTH);
    }

    public void playScript() {
        this.bar.setMaximum(10);

        this.dialog.open();

        final Display display = dialog.getDisplay();
        display.asyncExec(new Runnable() { //asyncExec syncExec
            @Override
            public void run() {
                try {
                    for (int i=0; i<10; i++) {
                        try {
                            Thread.sleep(1000); // To simulate a task execution
                        } catch (InterruptedException e) {}
                        bar.setSelection(i+1);
                        display.sleep();
                    }
                } finally {
                    dialog.close();
                }
            }
        });
        while (!dialog.isDisposed()) { 
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }
}

主要班级:

import org.eclipse.swt.widgets.Display;

public class MainWindow {

    protected Shell shell;

    public static void main(String[] args) {
        try {
            MainWindow window = new MainWindow();
            window.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void open() {
        Display display = Display.getDefault();
        shell = new Shell();
        shell.setSize(450, 300);
        shell.open();
        shell.layout();

        ProgressBox progressBox = new ProgressBox(shell, "Test");
        progressBox.playScript();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

}

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我认为你的问题是这两者的结合:

  1. 您有两个事件循环(while (!X.isDisposed())部分)
  2. 您在主线程上使用Thread.sleep()阻止了用户界面。
  3. 第2点会导致您的应用在显示进度条时无法响应用户互动,例如用户无法再关注窗口。

    另请注意,(至少对于您目前为止的代码而言)Dialog并非必要。我附上了一个代码示例,展示了如何做两件事:

    1. 在主窗口顶部设置模态窗口
    2. 使用Display#timerExec(int, Runnable)
    3. 定期更新用户界面

      protected ProgressBar bar;
      protected Shell       shell;
      
      public ProgressBox(Shell parent, final String name)
      {
          this.shell = new Shell(parent, SWT.APPLICATION_MODAL | SWT.TITLE);
          shell.setLayout(new FillLayout());
      
          bar = new ProgressBar(shell, SWT.SMOOTH);
      
          shell.setText(name);
          shell.pack();
          shell.open();
      }
      
      public void open()
      {
          final int max = 10;
      
          this.bar.setMaximum(max);
      
          new Thread(new Runnable()
          {
              @Override
              public void run()
              {
                  for (int i = 1; i <= max; i++)
                  {
                      if (bar == null || bar.isDisposed())
                      {
                          closeShell();
                          return;
                      }
                      else
                      {
                          final int index = i;
                          shell.getDisplay().asyncExec(new Runnable()
                          {
                              @Override
                              public void run()
                              {
                                  bar.setSelection(index);
                              }
                          });
                      }
      
                      try
                      {
                          Thread.sleep(1000);
                      }
                      catch (InterruptedException e)
                      {
                          closeShell();
                          e.printStackTrace();
                      }
                  }
      
                  closeShell();
              }
      
              private void closeShell()
              {
                  shell.getDisplay().asyncExec(new Runnable()
                  {
                      @Override
                      public void run()
                      {
                          shell.close();
                      }
                  });
              }
          }).start();
      }
      
      public static void main(String[] args)
      {
          Display display = Display.getDefault();
          Shell shell = new Shell();
          shell.setSize(450, 300);
          shell.open();
      
          new ProgressBox(shell, "Progress").open();
      
          while (!shell.isDisposed())
          {
              if (!display.readAndDispatch())
              {
                  display.sleep();
              }
          }
      }