如何在不冻结SWT GUI的前提下等待线程完成并获取用户输入
问题核心原因
- SWT 是单线程 UI 框架,所有 UI 组件的创建、属性修改、事件绑定操作都必须在 UI 线程(也就是 Display 线程)执行,你在自定义的 Openbox 子线程中创建 Text 组件、修改组件属性属于违规操作,会导致组件异常甚至程序崩溃。
- 你写的
while(!inputted) {continue;}属于忙等待逻辑,如果你是在 UI 线程执行这段循环,会直接卡住 UI 事件的处理,导致界面冻结;你自定义的 Thread 子类里写的带Test参数的run方法是自定义方法,线程启动后只会调用无参的run(),所以你写的等待逻辑根本没有执行。 - 你设计的「调用 input 方法后同步等待用户输入完成再返回内容」的逻辑,不能用空循环实现,要配合 SWT 内置的事件分发机制实现。
解决方案
不需要自己额外创建子线程处理 UI 逻辑,直接用 SWT 内置的事件循环方法处理等待逻辑即可,修改后的参考代码如下:
public String input(String prompt) { inputted = false; consoleText += prompt; console.setText(consoleText); // 直接在UI线程创建输入框,不要开子线程 consoleInput = new Text(shell, SWT.NONE); consoleInput.setBackground(SWTResourceManager.getColor(SWT.COLOR_DARK_CYAN)); consoleInput.setBounds(10, 10, 414, 21); consoleInput.setFocus(); // 自动聚焦到输入框 // 绑定回车事件 consoleInput.addListener(SWT.DefaultSelection, event -> { // 输入完成处理逻辑 String inputContent = consoleInput.getText(); consoleText += inputContent + "\n"; console.setText(consoleText); returnStr = inputContent; inputted = true; consoleInput.dispose(); // 销毁输入框 }); // 等待输入完成,主动处理UI事件避免冻结 Display display = shell.getDisplay(); while (!inputted) { // 处理所有待执行的UI事件 if (!display.readAndDispatch()) { // 无事件时休眠10ms,避免占用过高CPU display.sleep(); } } return returnStr; }
你之前写的 Input、Openbox 两个线程类可以直接删除,没有作用。
额外注意事项
如果后续你确实需要在业务子线程中操作 UI 组件,必须用 SWT 提供的线程切换方法包装操作:
Display.getDefault().asyncExec(() -> { // 这里写UI操作代码 });
内容的提问来源于stack exchange,提问作者maxbear123
相关产品推荐
相关产品推荐

