如何在条件仍有效时在独立线程延迟运行方法,实现可取消的延时错误提示
实现思路
当前场景基于JFace/SWT框架开发,UI操作必须在主线程执行,因此直接使用SWT原生提供的Display.timerExec()延迟API即可实现需求,无需手动创建独立线程,逻辑如下:
- 新增成员变量保存待执行的延迟报错任务
- 每次用户输入触发
checkState校验时,首先取消还未执行的历史延迟报错任务 - 校验通过则直接清空错误信息,无需执行后续逻辑
- 校验不通过则提交一个2秒后执行的报错任务,任务执行前如果用户再次输入会被直接取消,避免输入过程中频繁弹出错误提示
修改后的完整代码
private class DirectoryVarFieldEditor extends DirectoryFieldEditor { /** * Initial path for the Browse dialog. */ private File filterPath = null; // 保存待执行的延迟报错任务 private Runnable delayedErrorTask; // 报错延迟时长,单位毫秒 private static final int ERROR_SHOW_DELAY = 2000; public DirectoryVarFieldEditor(String name, String labelText, Composite parent) { //super( name, labelText, parent ); init(name, labelText); setErrorMessage(JFaceResources.getString("DirectoryFieldEditor.errorMessage")); setChangeButtonText(JFaceResources.getString("openBrowse")); setValidateStrategy(VALIDATE_ON_KEY_STROKE); createControl(parent); setEmptyStringAllowed(false); } // another code... @Override protected boolean doCheckState() { System.out.println("DirectoryVarFieldEditor.doCheckState()"); String fileName = getTextControl().getText(); fileName = fileName.trim(); fileName = TCA3DNKernel.expandEnvironmentVariables(fileName); if (fileName.length() == 0 && isEmptyStringAllowed()) return true; File file = new File(fileName); return file.isDirectory(); } @Override protected boolean checkState() { boolean result = false; boolean emptyStringAllowed = super.isEmptyStringAllowed(); Text textField = super.getTextControl(); String errorMessage = getErrorMessage(); if (emptyStringAllowed) { result = true; } if (textField == null) { result = false; } else { String txt = textField.getText(); result = (txt.trim().length() > 0) || emptyStringAllowed; } // call hook for subclasses result = result && doCheckState(); // 先取消所有未执行的历史延迟报错任务 if (delayedErrorTask != null) { Display.getDefault().timerExec(-1, delayedErrorTask); delayedErrorTask = null; } if (result) { clearErrorMessage(); } else { System.out.println("DirectoryVarFieldEditor.checkState()"); // 构造新的延迟报错任务 delayedErrorTask = () -> { // 执行前额外判断控件是否已销毁,避免空指针 if (getTextControl() != null && !getTextControl().isDisposed()) { showErrorMessage(errorMessage); } delayedErrorTask = null; }; // 提交2秒后执行的任务到UI线程队列 Display.getDefault().timerExec(ERROR_SHOW_DELAY, delayedErrorTask); } return result; } // another code... }
内容的提问来源于stack exchange,提问作者Michal Kotus
相关产品推荐
相关产品推荐

