Qt:从 C++ 向 QML 引擎抛出异常

Posted

技术标签:

【中文标题】Qt:从 C++ 向 QML 引擎抛出异常【英文标题】:Qt: Throwing an exception from C++ to QML engine 【发布时间】: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中检查该字符串是否真的包含电子邮件。 还有这个lists.qt-project.org/pipermail/interest/2015-April/016652.html 老实说,我不会费心处理异常,只需使用经典的返回码。这甚至与技术无关,但就我而言,我无法想象自己在一年前考虑某个项目 - 哦该死的......这个异常来自哪里以及它在哪里处理=) @evilruff,我想让它对将要使用我的组件的 JavaScript 开发人员更友好。 Q_INVOKABLE C++ 方法依赖于其他变量,例如,如果它们为 NULL,我想抛出一个 TypeError 说某个变量是“未定义” 你有没有得到这个答案?我试图做同样的事情...... 【参考方案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

参考:

https://doc.qt.io/qt-5/qjsengine.html#throwError

【讨论】:

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

以上是关于Qt:从 C++ 向 QML 引擎抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

从 SQL Server 函数向存储过程抛出异常

如何从 MFP 8 Java 适配器向客户端抛出用户异常?

如何从异步方法向调用者抛出异常?

C++的构造函数可以抛出异常么

如何在Qt中捕获异常?

从 WCF 抛出异常