【问题标题】:Qt: Throwing an exception from C++ to QML engineQt:从 C++ 向 QML 引擎抛出异常
【发布时间】:2016-12-30 18:03:45
【问题描述】:

当从QML 中的JavaScript 函数调用C++ 中编写的Q_INVOKABLE 方法时,如何抛出异常?该方法由 < MyApp > 类型的对象拥有,并通过调用 qmlRegisterType() 注册

例如,我有以下 QML 代码:

TextField {
    id: fld_recipient

    onEditingFinished: {
        try {
            var identity=myapp.identities.current_Identity;
            var company=identity.companies.current_Company;
            myapp.lookup_email(identity.identity_id,company.company_id,fld_recipient.text)
        } catch(e) {
            console.log(e);
        }
    }
}

这里,方法 MyApp::lookup_email() 进入服务器并搜索匹配的电子邮件地址。这个过程可能会因大量错误而停止,我希望 catch() 语句显示该错误。

这是如何在 C++ 端完成的?有点像这样:

void MyApp::lookup_email(int identity_id,int company_id,QString email) {

    ....

    error_code=server->lookup_email(identity_id,company_id,email);

    if (error_code) { /// throw an exception to QML engine, 
         ????? <= what goes here ?
    }
}

【问题讨论】:

  • 如果发生错误则返回一个空字符串,并在QML中检查该字符串是否真的包含电子邮件。
  • 老实说,我不会费心处理异常,只需使用经典的返回码。这甚至与技术无关,但就我而言,我无法想象自己在一年前考虑某个项目 - 哦该死的......这个异常来自哪里以及它在哪里处理=)
  • @evilruff,我想让它对将要使用我的组件的 JavaScript 开发人员更友好。 Q_INVOKABLE C++ 方法依赖于其他变量,例如,如果它们为 NULL,我想抛出一个 TypeError 说某个变量是“未定义”
  • 你有没有得到这个答案?我试图做同样的事情......

标签: c++ qt qml qt5


【解决方案1】:

Qml 不应包含任何业务逻辑,而应仅显示任何结果。如果您的应用程序遇到异常状态,请在业务逻辑中捕获异常并将结果/新状态呈现给用户。

如果您假设您的 (UI) 代码将使用不完整的数据调用,您应该忽略它。或者在调试级别使用断言。

【讨论】:

    【解决方案2】:

    以下代码 sn-p 显示了您可以如何使用QQmlEngine::throwError:

    #ifndef __MathTools__
    #define __MathTools__
    
    #include <QObject>
    #include <QQmlEngine>
    #include <QString>
    
    class MathTools : public QObject
    {
        Q_OBJECT
    
    public:
        MathTools(QObject* parent = nullptr) : QObject(parent)
        {
        }
    
        Q_INVOKABLE double divide(double a, double b)
        {
            if (b == 0.0)
            {
                qmlEngine(this)->throwError(tr("Division by zero error"));
                return 0.0;
            }
            return a / b;
        }
    };
    
    #endif
    

    在 QML 中使用时:

            Flickable {
                id: flickable
    
                anchors.fill: parent
                anchors.margins: 10
    
                contentWidth: columnLayout.width
                contentHeight: columnLayout.height
                clip: true
    
                ColumnLayout {
                    id: columnLayout
    
                    width: flickable.width
    
                    TextEdit {
                        id: firstTextEdit
                        Layout.fillWidth: true
                        font.pointSize: styles.textPointSize
                        selectByMouse: true
                    }
    
                    TextEdit {
                        id: secondTextEdit
                        Layout.fillWidth: true
                        font.pointSize: styles.textPointSize
                        selectByMouse: true
                    }
    
                    Button {
                        text: qsTr("Divide")
                        font.pointSize: styles.textPointSize
                        onClicked: {
                            resultTextEdit.text = "";
                            const first = parseFloat(firstTextEdit.text);
                            const second = parseFloat(secondTextEdit.text);
                            const result = mathTools.divide(first, second);
                            resultTextEdit.text = result;
                        }
                    }
    
                    Text {
                        id: resultTextEdit
                        Layout.fillWidth: true
                        font.pointSize: styles.textPointSize
                    }
                }
            }
    

    我看到尝试除以零时抛出 QML/Javascript 错误:

    qrc:/main.qml:58: Error: Division by zero error
    

    参考:

    【讨论】:

    • 在我的 QQuickItem 子类中这样尝试过:QQmlEngine::contextForObject(this)-&gt;engine()-&gt;throwError(QJSValue::SyntaxError, "Custom Error Message"); 不做任何事情。我错过了什么?
    • @mchiasson 从文档来看,它看起来不像 C++ 抛出,它只会在控件返回 JS 引擎时触发 JS 异常。换句话说,在最顶层的函数中使用它。
    • @mchiasson 我已更新我的答案以显示qmlEngine(this)-&gt;throwError(...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 2015-08-04
    相关资源
    最近更新 更多