# 插件对话框(PluginDialog)

PluginDialog 提供对话框的核心功能,包括显示、隐藏、按钮管理和各种事件监听。所有对话框都通过 pluginUI.buildDialog() 创建,支持丰富的配置选项和灵活的交互方式。

# 快速开始

// 简单的消息对话框
pluginUI.buildDialog()
    .setTitle("提示")
    .setMessage("这是一个简单的对话框")
    .setPositiveButton("{ok}", null)
    .show();

// 带列表的对话框
CharSequence[] items = {"选项1", "选项2", "选项3"};
pluginUI.buildDialog()
    .setTitle("请选择")
    .setItems(items, (dialog, which) -> {
        pluginUI.showToast("选择了:" + items[which]);
    })
    .show();

// 自定义视图对话框
PluginView view = pluginUI.buildVerticalLayout()
    .addEditText("input").hint("请输入内容")
    .addButton().text("提交").onClick(v -> {
        String text = v.getRootView().<PluginEditText>requireViewById("input").getText().toString();
        pluginUI.showToast("输入了:" + text);
    })
    .build();

pluginUI.buildDialog()
    .setTitle("自定义对话框")
    .setView(view)
    .show();

# 接口概览

# PluginDialog 接口

方法 说明
getPluginUI() 获取关联的 PluginUI 实例
show() 显示对话框
dismiss() 关闭对话框(触发 OnDismissListener)
cancel() 取消对话框(触发 OnCancelListener 和 OnDismissListener)
isShowing() 检查对话框是否正在显示
getPositiveButton() 获取积极按钮实例
getNegativeButton() 获取消极按钮实例
getNeutralButton() 获取中性按钮实例
setPositiveButton() 动态设置积极按钮
setNegativeButton() 动态设置消极按钮
setNeutralButton() 动态设置中性按钮
setView() 设置自定义视图
setTitle() 设置对话框标题
setMessage() 设置对话框消息
setCancelable() 设置是否可取消
setOnShowListener() 设置显示事件监听器
setOnDismissListener() 设置消失事件监听器
setOnCancelListener() 设置取消事件监听器
setOnKeyListener() 设置按键事件监听器

# Builder 接口

方法 说明
setTitle() 设置标题
setMessage() 设置消息内容
setPositiveButton() 设置积极按钮
setNegativeButton() 设置消极按钮
setNeutralButton() 设置中性按钮
setCancelable() 设置是否可取消
setOnShowListener() 设置显示事件监听器
setOnDismissListener() 设置消失事件监听器
setOnCancelListener() 设置取消事件监听器
setOnKeyListener() 设置按键事件监听器
setItems() 设置简单列表项
setMultiChoiceItems() 设置多选列表项
setSingleChoiceItems() 设置单选列表项
setView() 设置自定义视图
create() 创建对话框实例(不显示)
show() 创建并显示对话框

# 创建对话框

# buildDialog

PluginDialog.Builder buildDialog()

通过 pluginUI.buildDialog() 创建对话框构建器,使用链式调用配置对话框。

返回值: PluginDialog.Builder 对话框构建器实例

# create 和 show

// 方式一:创建但不显示
PluginDialog dialog = pluginUI.buildDialog()
    .setTitle("标题")
    .setMessage("内容")
    .create();
// 稍后显示
dialog.show();

// 方式二:创建并立即显示
PluginDialog dialog = pluginUI.buildDialog()
    .setTitle("标题")
    .setMessage("内容")
    .show();

注意:如果使用 create() 创建对话框,必须至少调用一次 show() 之后才能获取按钮实例,否则 getPositiveButton() 等方法会返回 null。

# 设置内容

# 标题和消息

Builder setTitle(CharSequence title)
Builder setMessage(CharSequence message)

设置对话框的标题和消息内容。

参数:

  • title / message - 标题或消息文本,支持 {key} 格式的本地化文本

示例:

pluginUI.buildDialog()
    .setTitle("{tip}")           // 使用本地化文本
    .setMessage("操作成功完成")
    .setPositiveButton("{ok}", null)
    .show();

提示{key} 格式会自动转换为本地化文本。关于本地化文本的详细说明请查看 本地化文本

动态修改:

PluginDialog dialog = pluginUI.buildDialog()
    .setTitle("原标题")
    .setMessage("原消息")
    .show();

// 显示后动态修改
dialog.setTitle("新标题");
dialog.setMessage("新消息");

# 列表项

# 简单列表

Builder setItems(CharSequence[] items, OnClickListener listener)

设置简单列表项,点击后对话框会自动关闭。

示例:

CharSequence[] items = {"选项1", "选项2", "选项3"};
pluginUI.buildDialog()
    .setTitle("请选择")
    .setItems(items, (dialog, which) -> {
        pluginUI.showToast("选择了:" + items[which]);
    })
    .show();

# 单选列表

Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, OnClickListener listener)

设置带单选按钮的列表,点击后对话框不会自动关闭。

参数:

  • items - 列表项文本数组
  • checkedItem - 初始选中项的索引,-1 表示无选中项
  • listener - 列表项点击监听器

示例:

CharSequence[] items = {"选项1", "选项2", "选项3"};
int[] selection = {1};  // 初始选中第二项

pluginUI.buildDialog()
    .setTitle("单选列表")
    .setSingleChoiceItems(items, selection[0], (dialog, which) -> {
        selection[0] = which;  // 记录选中位置
    })
    .setPositiveButton("{ok}", (dialog, which) -> {
        pluginUI.showToast("选中了:" + items[selection[0]]);
    })
    .show();

# 多选列表

Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, OnMultiChoiceClickListener listener)

设置多选列表,点击后对话框不会自动关闭。

参数:

  • items - 列表项文本数组
  • checkedItems - 对应每个列表项的初始选中状态
  • listener - 多选列表项点击监听器

示例:

CharSequence[] items = {"选项1", "选项2", "选项3", "选项4"};
boolean[] checked = {false, true, false, true};  // 初始选中第2、4项

pluginUI.buildDialog()
    .setTitle("多选列表")
    .setMultiChoiceItems(items, checked, (dialog, which, isChecked) -> {
        checked[which] = isChecked;  // 记录选中状态
    })
    .setPositiveButton("{ok}", (dialog, which) -> {
        StringBuilder sb = new StringBuilder("选中了:");
        for (int i = 0; i < checked.length; i++) {
            if (checked[i]) {
                sb.append(' ').append(items[i]);
            }
        }
        pluginUI.showToast(sb);
    })
    .show();

# 自定义视图

Builder setView(PluginView view)
void setView(PluginView view)

设置自定义视图,将显示在对话框的内容区域。

示例:

// 创建自定义视图
PluginView view = pluginUI.buildVerticalLayout()
    .addEditText("input").hint("请输入姓名")
    .addEditText("email").hint("请输入邮箱")
    .build();

// 在对话框中显示
pluginUI.buildDialog()
    .setTitle("用户信息")
    .setView(view)
    .setPositiveButton("{ok}", (dialog, which) -> {
        PluginEditText input = view.requireViewById("input");
        PluginEditText email = view.requireViewById("email");
        pluginUI.showToast("姓名:" + input.getText() + "\n邮箱:" + email.getText());
    })
    .show();

提示:如果自定义视图中包含 EditText 并希望自动弹出输入法,需要调用 editText.requestFocusAndShowIME()

# 对话框按钮

# 三种按钮

对话框支持三种按钮,每种按钮有对应的标识符:

按钮类型 标识符 常用场景
积极按钮(Positive) BUTTON_POSITIVE (-1) "确定"、"保存"、"是"
消极按钮(Negative) BUTTON_NEGATIVE (-2) "取消"、"放弃"、"否"
中性按钮(Neutral) BUTTON_NEUTRAL (-3) "稍后"、"跳过"

# 设置按钮

Builder setPositiveButton(CharSequence text, OnClickListener listener)
Builder setNegativeButton(CharSequence text, OnClickListener listener)
Builder setNeutralButton(CharSequence text, OnClickListener listener)

设置对话框按钮。点击按钮后,对话框会自动关闭并触发监听器。

参数:

  • text - 按钮显示的文本,支持 {key} 格式的本地化文本
  • listener - 按钮点击事件监听器,可为 null

示例:

pluginUI.buildDialog()
    .setTitle("确认操作")
    .setMessage("是否继续?")
    .setPositiveButton("是", (dialog, which) -> {
        // which == PluginDialog.BUTTON_POSITIVE
        pluginUI.showToast("点击了积极按钮");
    })
    .setNegativeButton("否", (dialog, which) -> {
        // which == PluginDialog.BUTTON_NEGATIVE
        pluginUI.showToast("点击了消极按钮");
    })
    .setNeutralButton("稍后", (dialog, which) -> {
        // which == PluginDialog.BUTTON_NEUTRAL
        pluginUI.showToast("点击了中性按钮");
    })
    .show();

# 获取按钮

PluginButton getPositiveButton()
PluginButton getNegativeButton()
PluginButton getNeutralButton()

获取对话框的按钮实例,可用于自定义按钮行为。

返回值: PluginButton 按钮实例,如果未设置则返回 null

注意:如果使用 create() 创建对话框,必须至少调用一次 show() 之后才能获取按钮实例。

# 点击不关闭

默认情况下,点击对话框按钮会自动关闭对话框。如果需要点击后不关闭,可以通过以下方式实现:

// 先创建对话框,设置按钮的 listener 为 null
PluginDialog dialog = pluginUI.buildDialog()
    .setTitle("计数器")
    .setMessage("点击10次后对话框消失")
    .setPositiveButton("点我", null)
    .show();

// 获取按钮并覆盖点击事件
int[] count = {0};
dialog.getPositiveButton().setOnClickListener(view -> {
    count[0]++;
    pluginUI.showToast("点击了 " + count[0] + " 次");
    if (count[0] == 10) {
        dialog.dismiss();  // 手动关闭对话框
    }
});

关键点:

  1. setPositiveButton() 时传入 null 作为监听器
  2. 调用 show() 之后获取按钮实例
  3. 使用 setOnClickListener() 设置自定义点击事件
  4. 需要时手动调用 dialog.dismiss() 关闭对话框

# 显示和关闭

# show

void show()

显示对话框。如果对话框已经显示,此方法无效果。

# dismiss 和 cancel

void dismiss()
void cancel()

关闭对话框的两种方式:

  • dismiss() - 直接关闭,触发 OnDismissListener 回调
  • cancel() - 取消关闭,触发 OnCancelListener 和 OnDismissListener 回调

示例:

PluginDialog dialog = pluginUI.buildDialog()
    .setTitle("测试")
    .setOnDismissListener(d -> pluginUI.showToast("对话框消失"))
    .setOnCancelListener(d -> pluginUI.showToast("对话框取消"))
    .show();

// 直接关闭:只触发 OnDismissListener
dialog.dismiss();

// 取消关闭:先触发 OnCancelListener,再触发 OnDismissListener
dialog.cancel();

# isShowing

boolean isShowing()

检查对话框是否正在显示。

返回值: true 表示正在显示,false 表示已关闭或未显示

# 可取消性

# setCancelable

Builder setCancelable(boolean cancelable)
void setCancelable(boolean cancelable)

设置对话框是否可以通过返回键或点击外部区域取消。

参数:

  • cancelable - true 表示可取消,false 表示不可取消

示例:

// 不可取消的对话框
pluginUI.buildDialog()
    .setTitle("处理中")
    .setMessage("请稍候,点击外部或返回键无法取消")
    .setCancelable(false)
    .setPositiveButton("{ok}", null)
    .show();

# 事件监听

# OnShowListener

Builder setOnShowListener(OnShowListener listener)
void setOnShowListener(OnShowListener listener)

设置对话框显示事件监听器,在对话框显示时触发。

示例:

pluginUI.buildDialog()
    .setTitle("显示事件")
    .setOnShowListener(dialog -> {
        pluginUI.showToast("对话框已显示");
    })
    .show();

# OnDismissListener

Builder setOnDismissListener(OnDismissListener listener)
void setOnDismissListener(OnDismissListener listener)

设置对话框消失事件监听器,在对话框消失时触发(包括取消、按钮点击等所有关闭方式)。

示例:

pluginUI.buildDialog()
    .setTitle("消失事件")
    .setOnDismissListener(dialog -> {
        pluginUI.showToast("对话框已消失");
    })
    .show();

# OnCancelListener

Builder setOnCancelListener(OnCancelListener listener)
void setOnCancelListener(OnCancelListener listener)

设置对话框取消事件监听器,当用户通过返回键或点击外部区域取消对话框时触发。

示例:

pluginUI.buildDialog()
    .setTitle("取消事件")
    .setMessage("点击外部或按返回键试试")
    .setOnCancelListener(dialog -> {
        pluginUI.showToast("对话框已取消");
    })
    .show();

# OnKeyListener

Builder setOnKeyListener(OnKeyListener listener)
void setOnKeyListener(OnKeyListener listener)

设置按键事件监听器,用于处理对话框的按键事件。

参数:

  • listener - 按键事件监听器

监听器方法:

boolean onKey(PluginDialog dialog, int keyCode, KeyEvent event)
  • 返回 true 表示事件已处理,不再继续传递
  • 返回 false 表示继续传递事件

示例:自定义返回键行为

pluginUI.buildDialog()
    .setTitle("自定义返回键")
    .setMessage("点击外部不取消,按返回键才取消")
    .setCancelable(false)  // 先设置不可取消
    .setOnKeyListener((dialog, keyCode, event) -> {
        // 按下返回键时手动取消
        if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) {
            pluginUI.showToast("按下了返回键");
            dialog.cancel();
            return true;  // 事件已处理
        }
        return false;
    })
    .setPositiveButton("{close}", null)
    .show();

# OnClickListener

interface OnClickListener {
    void onClick(PluginDialog dialog, int which);
}

按钮或列表项点击事件监听器。

参数:

  • dialog - 触发事件的对话框实例
  • which - 被点击的按钮标识符或列表项索引
    • 对于按钮:BUTTON_POSITIVEBUTTON_NEGATIVEBUTTON_NEUTRAL
    • 对于列表项:对应的数组索引

# OnMultiChoiceClickListener

interface OnMultiChoiceClickListener {
    void onClick(PluginDialog dialog, int which, boolean isChecked);
}

多选列表项点击事件监听器。

参数:

  • dialog - 触发事件的对话框实例
  • which - 被点击的列表项索引
  • isChecked - 该列表项的新选中状态

# 工具对话框

MT 插件提供了三个便捷的对话框工具类,用于常见的加载和进度提示场景。这些工具类封装了对话框的创建和配置,使用更加简单。

# LoadingDialog

加载对话框提供带圆形进度条和双行文本的加载提示,适用于需要显示加载状态的场景。

# 创建和显示

LoadingDialog loadingDialog = new LoadingDialog(pluginUI);

// 立即显示
loadingDialog.show();

// 延迟显示(默认延迟 200ms)
loadingDialog.showDelay();

// 自定义延迟时间
loadingDialog.showDelay(500);  // 延迟 500ms 显示

提示:使用 showDelay() 可以避免短时间任务导致的闪烁效果。如果任务在延迟时间内完成,对话框将不会显示。

# 设置消息

LoadingDialog loadingDialog = new LoadingDialog(pluginUI);

// 设置主要消息
loadingDialog.setMessage("正在处理文件...");

// 设置次要消息
loadingDialog.setSecondaryMessage("已完成 50 个文件");

// 隐藏次要消息
loadingDialog.setSecondaryMessage(null);

loadingDialog.show();

说明:

  • 主要消息默认显示为 {loading}("加载中...")
  • 次要消息默认隐藏,设置非空值后才会显示
  • 可以在子线程中调用这些方法,内部已处理线程切换

# 可取消性

LoadingDialog 继承自 BaseCancelableDialog,支持双击返回键取消。

LoadingDialog loadingDialog = new LoadingDialog(pluginUI);

// 设置为可取消
loadingDialog.setCancelable();  // 等同于 setCancelable(true)

// 设置取消监听器
loadingDialog.setOnCancelListener(dialog -> {
    pluginUI.showToast("用户取消了加载");
    // 执行清理操作...
});

loadingDialog.show();

注意:启用可取消后,用户需要在 2 秒内连续按两次返回键才能取消对话框。第一次按下时会提示"再按一次取消",第二次按下才会触发取消回调。

# 关闭对话框

// 关闭对话框(线程安全)
loadingDialog.dismiss();

// 检查是否正在显示
if (loadingDialog.isShowing()) {
    loadingDialog.dismiss();
}

线程安全:dismiss() 方法会自动切换到 UI 线程执行,可以在子线程中安全调用。

# ProgressDialog

进度对话框提供水平进度条,适用于需要显示具体进度的场景。

# 创建和显示

ProgressDialog progressDialog = new ProgressDialog(pluginUI);

// 设置标题和消息
progressDialog
    .setTitle("正在导出")
    .setMessage("正在导出文件...")
    .show();

注意:show() 方法必须在 UI 线程中调用。

# 设置内容

ProgressDialog progressDialog = new ProgressDialog(pluginUI);

// 设置标题
progressDialog.setTitle("文件处理");

// 设置消息(可选)
progressDialog.setMessage("正在处理第 1 个文件");

// 隐藏消息
progressDialog.setMessage(null);

progressDialog.show();

# 进度设置

ProgressDialog progressDialog = new ProgressDialog(pluginUI);

// 设置最大进度值(默认为 100)
progressDialog.setMaxProgress(200);

// 设置当前进度
progressDialog.setProgress(50);

// 设置次要进度(灰色进度条)
progressDialog.setSecondaryProgress(80);

// 设置为不确定进度模式(显示循环动画)
progressDialog.setIndeterminate();

// 切换回确定进度模式
progressDialog.setIndeterminate(false);

progressDialog.show();

说明:

  • 默认最大进度值为 100
  • 次要进度用于显示缓冲或预加载进度
  • 不确定进度模式适用于无法估算完成时间的任务
  • 可以在子线程中调用这些方法,内部已处理线程切换

# 可取消性

ProgressDialog progressDialog = new ProgressDialog(pluginUI);

// 设置为可取消
progressDialog.setCancelable();

// 设置取消监听器
progressDialog.setOnCancelListener(dialog -> {
    pluginUI.showToast("用户取消了导出");
    // 停止后台任务...
});

progressDialog.show();

# 关闭对话框

// 关闭对话框(线程安全)
progressDialog.dismiss();

// 检查是否正在显示
if (progressDialog.isShowing()) {
    progressDialog.dismiss();
}

# DualProgressDialog

双进度对话框提供两个水平进度条,适用于需要同时显示子任务和总任务进度的场景。

# 创建和显示

DualProgressDialog dualProgressDialog = new DualProgressDialog(pluginUI);

// 设置标题和消息
dualProgressDialog
    .setTitle("批量处理")
    .setMessage("正在处理文件 1/10")
    .show();

# 设置内容

DualProgressDialog dualProgressDialog = new DualProgressDialog(pluginUI);

// 设置标题
dualProgressDialog.setTitle("批量导出");

// 设置消息(可选)
dualProgressDialog.setMessage("正在处理: example.txt");

// 隐藏消息
dualProgressDialog.setMessage(null);

dualProgressDialog.show();

# 进度设置

DualProgressDialog dualProgressDialog = new DualProgressDialog(pluginUI);

// 设置子进度条的最大值
dualProgressDialog.setMaxSubProgress(100);

// 设置总进度条的最大值
dualProgressDialog.setMaxTotalProgress(10);

// 设置子进度(当前文件的处理进度)
dualProgressDialog.setSubProgress(45);

// 设置总进度(已完成的文件数)
dualProgressDialog.setTotalProgress(3);

dualProgressDialog.show();

说明:

  • 子进度条通常用于显示当前任务的进度
  • 总进度条显示标签为 {dual_progress_dialog_total}("总进度")
  • 可以在子线程中调用这些方法,内部已处理线程切换

# 可取消性

DualProgressDialog dualProgressDialog = new DualProgressDialog(pluginUI);

// 设置为可取消
dualProgressDialog.setCancelable();

// 设置取消监听器
dualProgressDialog.setOnCancelListener(dialog -> {
    pluginUI.showToast("用户取消了批量处理");
    // 停止批量任务...
});

dualProgressDialog.show();

# 关闭对话框

// 关闭对话框(线程安全)
dualProgressDialog.dismiss();

// 检查是否正在显示
if (dualProgressDialog.isShowing()) {
    dualProgressDialog.dismiss();
}

# 完整示例

# 确认对话框

pluginUI.buildDialog()
    .setTitle("删除文件")
    .setMessage("确定要删除该文件吗?此操作不可恢复。")
    .setPositiveButton("删除", (dialog, which) -> {
        // 执行删除操作
        pluginUI.showToast("文件已删除");
    })
    .setNegativeButton("{cancel}", null)
    .show();

# 输入对话框

// 创建输入视图
PluginView view = pluginUI.buildVerticalLayout()
    .addEditText("input").hint("请输入内容")
    .build();

// 获取输入框并自动弹出输入法
PluginEditText input = view.requireViewById("input");
input.requestFocusAndShowIME();

// 显示对话框
pluginUI.buildDialog()
    .setTitle("输入")
    .setView(view)
    .setPositiveButton("{ok}", (dialog, which) -> {
        String text = input.getText().toString();
        if (text.isEmpty()) {
            pluginUI.showToast("输入不能为空");
        } else {
            pluginUI.showToast("输入了:" + text);
        }
    })
    .setNegativeButton("{cancel}", null)
    .show();

# 表单对话框

// 创建表单视图
PluginView form = pluginUI.buildVerticalLayout()
    .addHorizontalLayout().children(row -> row
        .addTextView("label1").text("用户名")
        .addEditText("username").hint("请输入用户名")
    )
    .addHorizontalLayout().children(row -> row
        .addTextView("label2").text("密码")
        .addEditText("password").hint("请输入密码")
    )
    .addHorizontalLayout().children(row -> row
        .addTextView("label3").text("邮箱")
        .addEditText("email").hint("请输入邮箱")
    )
    .unifyWidth("label1", "label2", "label3")
    .build();

// 显示对话框
pluginUI.buildDialog()
    .setTitle("注册")
    .setView(form)
    .setPositiveButton("注册", (dialog, which) -> {
        String username = form.<PluginEditText>requireViewById("username").getText().toString();
        String password = form.<PluginEditText>requireViewById("password").getText().toString();
        String email = form.<PluginEditText>requireViewById("email").getText().toString();

        if (username.isEmpty() || password.isEmpty() || email.isEmpty()) {
            pluginUI.showToast("请填写完整信息");
        } else {
            pluginUI.showToast("注册成功");
        }
    })
    .setNegativeButton("{cancel}", null)
    .show();

# 本地化文本

// MT 内置了常用的对话框文本,可直接使用
pluginUI.buildDialog()
    .setTitle("{tip}")          // 提示
    .setMessage("{success}")    // 成功
    .setPositiveButton("{ok}", null)      // 确定
    .setNegativeButton("{cancel}", null)  // 取消
    .show();

提示:MT 内置了常用的对话框词条,如 {tip}{warning}{error}{ok}{cancel}{close} 等,可直接在插件中使用。完整列表请查看 MT 内置词条

# 加载和进度对话框

以下示例展示如何在异步任务中使用工具对话框:

// 示例1:LoadingDialog - 简单加载任务
LoadingDialog loadingDialog = new LoadingDialog(pluginUI);
loadingDialog
    .setMessage("正在加载数据...")
    .setCancelable()
    .setOnCancelListener(dialog -> {
        // 用户取消了加载
    })
    .showDelay();  // 延迟显示,避免闪烁

// 在后台线程中执行任务
new Thread(() -> {
    try {
        // 执行耗时操作...
        Thread.sleep(2000);

        // 任务完成,关闭对话框
        loadingDialog.dismiss();
        pluginUI.showToast("加载完成");
    } catch (Exception e) {
        loadingDialog.dismiss();
        pluginUI.showToast("加载失败: " + e.getMessage());
    }
}).start();

// 示例2:ProgressDialog - 单个文件处理
ProgressDialog progressDialog = new ProgressDialog(pluginUI);
progressDialog
    .setTitle("处理文件")
    .setMaxProgress(100)
    .show();

new Thread(() -> {
    try {
        for (int i = 0; i <= 100; i++) {
            // 更新进度和消息(线程安全)
            int progress = i;
            progressDialog
                .setProgress(progress)
                .setMessage("已完成 " + progress + "%");

            Thread.sleep(50);  // 模拟处理
        }

        progressDialog.dismiss();
        pluginUI.showToast("处理完成");
    } catch (Exception e) {
        progressDialog.dismiss();
        pluginUI.showToast("处理失败: " + e.getMessage());
    }
}).start();

// 示例3:DualProgressDialog - 批量文件处理
DualProgressDialog dualProgressDialog = new DualProgressDialog(pluginUI);
dualProgressDialog
    .setTitle("批量处理文件")
    .setMaxSubProgress(100)    // 子进度:当前文件进度
    .setMaxTotalProgress(10)   // 总进度:文件总数
    .setCancelable()
    .setOnCancelListener(dialog -> {
        // 用户取消了批量处理
    })
    .show();

new Thread(() -> {
    try {
        String[] files = {"file1.txt", "file2.txt", "file3.txt", "file4.txt", "file5.txt"};

        for (int fileIndex = 0; fileIndex < files.length; fileIndex++) {
            String fileName = files[fileIndex];

            // 检查是否被取消
            if (dualProgressDialog.isCanceled()) {
                break;
            }

            // 更新当前文件名
            dualProgressDialog.setMessage("正在处理: " + fileName);

            // 处理当前文件
            for (int subProgress = 0; subProgress <= 100; subProgress += 10) {
                dualProgressDialog.setSubProgress(subProgress);
                Thread.sleep(100);  // 模拟处理
            }

            // 更新总进度
            dualProgressDialog.setTotalProgress(fileIndex + 1);
        }

        dualProgressDialog.dismiss();

        if (dualProgressDialog.isCanceled()) {
            pluginUI.showToast("已取消处理");
        } else {
            pluginUI.showToast("批量处理完成");
        }
    } catch (Exception e) {
        dualProgressDialog.dismiss();
        pluginUI.showToast("处理失败: " + e.getMessage());
    }
}).start();

# 相关接口