【问题标题】:Updating SWT periodically causes GUI to freeze定期更新 SWT 会导致 GUI 冻结
【发布时间】:2017-03-09 00:08:06
【问题描述】:

问题:定期更新 GUI 字段时 SWT 冻结。

我想要一个基于 SWT 的带有文本字段的 GUI,值会定期递增。

  1. 最初我从单独的线程访问 textField 导致抛出异常:

线程“Thread-0”org.eclipse.swt.SWTException 中的异常:无效 org.eclipse.swt.SWT.error(SWT.java:4533) 处的线程访问 org.eclipse.swt.SWT.error(SWT.java:4448) 在 org.eclipse.swt.SWT.error(SWT.java:4419) 在 org.eclipse.swt.widgets.Widget.error(Widget.java:482) 在 org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:373) 在 org.eclipse.swt.widgets.Text.setText(Text.java:2311) 在 regreon.Incrementing.lambda$0(Incrementing.java:62) 在 java.lang.Thread.run(Thread.java:745)

  1. 阅读 SWT 文档后(感谢 @marko-topolnik) - 我尝试在循环中使用 display.SyncExec(Runnable r)display.AsyncExec(Runnable r) 和调用 Thread.sleep 的 runnable。但这导致整个事情都冻结了。 代码如下:

    打包任何东西; 导入 org.eclipse.swt.widgets.Display; 导入 org.eclipse.swt.widgets.Shell; 导入 org.eclipse.swt.widgets.Text; 导入 org.eclipse.swt.SWT;

    公共类 FreezingGUI {

    protected Shell shell;
    private Text text;
    
    public static void main(String[] args) {
        try {
            FreezingGUI window = new FreezingGUI();
            window.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void open() {
        Display display = Display.getDefault();
        createContents();
        shell.open();
        shell.layout();
    
        // HOW TO DO THAT???
        display.syncExec(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Integer i = Integer.parseInt(text.getText()) + 1;
                    text.setText(i.toString());
                }
            }
        }
        );
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }
    
    protected void createContents() {
        shell = new Shell();
        shell.setSize(450, 300);
        shell.setText("SWT Application");
    
        text = new Text(shell, SWT.BORDER);
        text.setEditable(false);
        text.setText("0");
        text.setBounds(30, 32, 78, 26);
    }
    

    }

如何避免冻结和抛出异常?

【问题讨论】:

标签: java multithreading swt


【解决方案1】:

查看您的代码,您的 UI 冻结的原因是因为您正在 Display.sync 上执行一个可运行的对象,但由于 while(true) 循环而永远不会返回,因此,其他 UI 线程没有机会执行执行和 UI 冻结。您需要做的是使用 Displasy.asyncRunnable ,而不是使用 while(true) 来运行一个调度程序或另一个线程,该线程每隔 x 秒休眠一次,执行 runnable 以进行您想要的更新,这样其他 UI 线程可以运行以防止您的 UI 冻结。

【讨论】:

    【解决方案2】:

    任何更改 UI 对象的 SWT 操作都必须在 SWT 用户界面线程上运行。

    在您的情况下,text.setText(i.toString()); 行是 SWT UI 操作,并且在不同的线程中运行。

    您可以使用DisplayasyncExecsyncExec 方法在UI 线程中运行一些代码。所以替换:

    text.setText(i.toString());
    

    final String newText = i.toString();
    Display.getDefault().asyncExec(() -> text.setText(newText));
    

    (这是假设您使用的是 Java 8)。

    使用 asyncExec 将异步更新 UI。如果您想暂停线程直到更新完成,请改用syncExec

    如果您使用的是 Java 7 或更早版本:

     final String newText = i.toString();
     Display.getDefault().asyncExec(new Runnable() {
        @Override
        public void run() {
          text.setText(newText);
        }
     });
    

    请注意,您还应该检查正在处理的Shell 并停止您的后台线程。如果您不这样做,您将在关闭应用程序时收到错误消息。您的代码递增i 也是错误的。该线程有效:

    new Thread(() -> {
        for (int i = 1; true; i++) {
            try {
                Thread.sleep(1000);
            } catch (final InterruptedException e) {
                return;
            }
    
            if (shell.isDisposed())  // Stop thread when shell is closed
              break;
    
            final String newText = Integer.toString(i);
            Display.getDefault().asyncExec(() -> text.setText(newText));
        }
    }).start();
    

    【讨论】:

    • 我想在循环中添加更新。我尝试了 asyncExec 和 SyncExec。当我添加 Thread.sleep() 时,两者都会冻结。
    • Thread.sleep 必须asyncExec 代码中,您必须只有text.setText 方法,如我所示。让 UI 线程进入睡眠状态会导致 UI 冻结。
    • 我用线程的完整代码更新了答案 - 这绝对有效。
    • 检查过,效果很好。非常感谢。对于 SWT 的新手来说,你必须创建带有 Runnable 的线程,其中包含另一个 Runnable。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 2017-12-03
    • 1970-01-01
    • 2021-04-15
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多