如何用SWT制作带自动倒计时的自动关闭对话框(10秒无操作默认选No)
实现SWT带自动倒计时的确认对话框
我来帮你搞定这个需求!这里提供两种可行的实现思路,优先推荐自定义对话框方案(能实时显示剩余时间,体验更好),也会附上基于默认MessageDialog的简化版:
方案一:自定义带实时倒计时的对话框
这种方式可以灵活控制界面元素,实时更新倒计时显示,完全符合你的需求:
完整示例代码
import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import java.io.File; public class CountdownConfirmDialog { private static int countdownSeconds = 10; private static Shell dialogShell; private static boolean userResponded = false; public static void main(String[] args) { Display display = new Display(); Shell mainShell = new Shell(display); mainShell.setText("主程序窗口"); mainShell.setSize(300, 200); mainShell.open(); // 模拟你的场景:检测data.ini文件是否存在 String pa = System.getProperty("user.dir"); // 示例路径,替换成你的实际路径 File g = new File(pa + "\\data.ini"); if (g.exists()) { showCountdownDialog(display, mainShell); } while (!mainShell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } private static void showCountdownDialog(Display display, Shell parent) { // 创建模态对话框 dialogShell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); dialogShell.setText("操作确认"); dialogShell.setLayout(new GridLayout(2, false)); // 提示文本 Label messageLabel = new Label(dialogShell, SWT.NONE); messageLabel.setText("请在10秒内完成选择,超时将默认选择「否」:"); messageLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); // 倒计时显示标签 Label countdownLabel = new Label(dialogShell, SWT.NONE); countdownLabel.setText("剩余时间:" + countdownSeconds + "秒"); countdownLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); // 「是」按钮 Button yesBtn = new Button(dialogShell, SWT.PUSH); yesBtn.setText("是"); yesBtn.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); yesBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { userResponded = true; handleDialogResult(true); } }); // 「否」按钮 Button noBtn = new Button(dialogShell, SWT.PUSH); noBtn.setText("否"); noBtn.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); noBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { userResponded = true; handleDialogResult(false); } }); dialogShell.pack(); dialogShell.open(); // 启动倒计时计时器 startCountdownTimer(display, countdownLabel); } private static void startCountdownTimer(Display display, Label countdownLabel) { // SWT安全的定时任务:每隔1秒执行一次 display.timerExec(1000, new Runnable() { @Override public void run() { // 如果用户已操作或对话框已关闭,停止计时 if (userResponded || dialogShell.isDisposed()) { return; } countdownSeconds--; countdownLabel.setText("剩余时间:" + countdownSeconds + "秒"); if (countdownSeconds <= 0) { // 超时,默认选择「否」 handleDialogResult(false); } else { // 继续下一秒倒计时 display.timerExec(1000, this); } } }); } private static void handleDialogResult(boolean isYesSelected) { if (!dialogShell.isDisposed()) { dialogShell.dispose(); } // 这里处理你的业务逻辑 if (isYesSelected) { System.out.println("用户选择了「是」"); // 执行「是」对应的操作 } else { System.out.println("用户选择了「否」或超时默认选择「否」"); // 执行「否」对应的操作 } // 重置参数,方便下次调用对话框 countdownSeconds = 10; userResponded = false; } }
关键逻辑解释
Display.timerExec():这是SWT中安全执行UI定时任务的方式,它会把任务放到UI线程的事件队列中,避免多线程操作UI的安全问题,每隔1秒更新一次倒计时。- 用户操作跟踪:用
userResponded变量标记用户是否已经点击按钮,防止计时任务在用户操作后继续执行。 - 模态对话框:设置
SWT.APPLICATION_MODAL确保对话框弹出时,用户无法操作主窗口,符合确认类对话框的交互逻辑。
方案二:基于默认MessageDialog的简化版
如果你不想自定义界面,只是需要超时自动关闭对话框并默认选「否」,可以用这个简化方案(缺点是无法实时显示倒计时):
import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.jface.dialogs.MessageDialog; import java.io.File; public class SimpleCountdownDialog { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setText("主窗口"); shell.setSize(300, 200); shell.open(); String pa = System.getProperty("user.dir"); File g = new File(pa + "\\data.ini"); if (g.exists()) { // 创建确认对话框,默认选中索引1的按钮(「否」) MessageDialog dialog = new MessageDialog( shell, "确认操作", null, "请在10秒内选择,超时将默认选择「否」", MessageDialog.CONFIRM, new String[]{"是", "否"}, 1 ); // 10秒后自动关闭对话框 display.timerExec(10000, () -> { if (!dialog.getShell().isDisposed()) { dialog.getShell().close(); } }); // 打开对话框并获取结果 int result = dialog.open(); if (result == 0) { System.out.println("用户主动选择了「是」"); } else { System.out.println("用户选择了「否」或超时默认选择「否」"); } } while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }
这个方案利用MessageDialog的默认选中按钮参数,结合timerExec在10秒后关闭对话框,此时dialog.open()会返回默认选中的按钮索引(即「否」的索引1)。
内容的提问来源于stack exchange,提问作者A. Allen
相关产品推荐
相关产品推荐

