首页 > 解决方案 > 在事件循环之后执行信号

问题描述

在我的 .qml 文件中,当Button按下 a 时,它会发出一个信号,并采取一些行动。此操作需要很长时间(它正在加密数据),我希望按钮在此操作开始之前自行“取消推送”,因此我可以在顶部显示进度条。

我知道 Qt 有事件循环,不知何故,我需要在这个事件循环之后发出这个信号,或者当 GUI 完成所有对象的 Paint() 时,所以按钮显示为未按下。

这是怎么做到的?

这是在信号上执行的代码,繁重的过程是aewm_obj.save_account(key,account),在台式机上需要 2 秒,在 Android 上需要 10 秒:

function save_account() {
    if (fld_password1.length===0) {
        if (account.type==WalletAccount.WACCT_TYPE_FULL) {
            return
        }
    }

    if (fld_password1.text!==fld_password2.text) {
        console.log("passwords do not match")
    } else {
        btn_save.enabled=true;
        if (account.type==WalletAccount.WACCT_TYPE_FULL) {
            key.password=fld_password1.text
            account.password=fld_password1.text
        }
        btn_save.enabled=false
        encrypting_message.open()
        if (aewm_obj.save_account(key,account)) {
            encrypting_message.close()
            accounts_root.back_to_accounts()
        } else {
            encrypting_message.close()
        }
    }
}

问题是,带有进度条的对话框在繁重的过程完成后显示,但它之前被调用过。发生这种情况是因为显示和隐藏组件的事件循环处理得太晚了。

标签: qtqml

解决方案


使用超时为 0 的单次计时器来排队返回事件循环后将触发的事件。在 C++ 中,这通常看起来像:

QTimer::singleShot(0, [] { /* do something */ });

QML 等价物是:

Timer {
    interval: 0; running: true; repeat: false
    onTriggered: /* do something */
}

推荐阅读