You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:04:22