如何在 QML 中模拟 C 风格的“ifdef”宏?

rig*_*717 9 macros qt qml qt5

我需要关闭 QML 代码的某些部分,因为这段代码是为了演示目的而完成的,它将在最终版本中删除。但是该产品将与这些演示功能一起使用很长时间,因此我不能使用带有演示功能的单独分支并不断将所有新功能合并到该分支 - 只是不方便。因此,运行此代码会很好,但在需要时可以轻松关闭和/或删除。在 C 和 C++ 中,我ifdef为此使用宏,但在 QML 中是否可以这样做?

rig*_*717 7

正如@Mark 所建议的,上下文属性可以在 QML 中用于在运行时决定是否启用某个宏,但是他提供的示例并未解决这种情况,当您需要根据此决定实例化对象时,但仅在代码块内覆盖大小写。所以我将提供我所做的完整示例。

在我的例子中,只有在编译时定义了宏时,我才向 QML 公开了一个类:

主.cpp :

#ifdef SMTP_SUPPORT
qmlRegisterType<SmtpClientHelper>("com.some.plugin", 1, 0, "SmtpClient");
engine.rootContext()->setContextProperty("SMTP_SUPPORT", QVariant(true));
#else
engine.rootContext()->setContextProperty("SMTP_SUPPORT", QVariant(false));
#endif // SMTP_SUPPORT
Run Code Online (Sandbox Code Playgroud)

然后在 QML 端我检查这个宏并决定是否必须创建 SmtpClient 对象:

qml :

import QtQuick 2.0;
import com.some.plugin 1.0

Item {
    id: root
    // ...

    property var smtpClient // No inside any function, need to instantiate the object

    Component.onCompleted: {
        if (SMTP_SUPPORT) {
            smtpClient = Qt.createQmlObject('                                                 \
                import QtQuick 2.0;                                                           \
                import com.some.plugin 1.0;                                                   \
                SmtpClient {                                                                  \
                    id: smtpClient;                                                           \
                                                                                              \
                    function setSenderEmail(email) {                                          \
                        senderEmail = email;                                                  \
                        storage.save("common", "clientEmail", email);                         \
                    }                                                                         \
                }                                                                             \
            ', root, "SmtpClient");
        }
    }

    // Reference smtpClient normally, like if it was statically created
    TextInput {
        id: senderEmailLogin
        anchors.fill: parent
        font.pixelSize: Globals.defaultFontSize
        text: smtpClient ? smtpClient.senderEmail : ""
        onEditingFinished: if (smtpClient) smtpClient.setSenderEmail(text)
        activeFocusOnPress: true
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为 Loader 也应该完成这项工作,因此您可以创建一个单独的组件,如果定义了 C++ 宏,则在 LoadersourcesourceComponent属性中引用它,但我不确定,因为不确定是否会静态检查该组件(在我的情况下) )SmtpClient类型可用

  • 我知道这是*正确的*解决方案,但它也是一个*糟糕的*解决方案。荒谬的是,为了实现经过时间考验的标准预编译器行为,我们必须使用文本字符串来开始实现整个组件和功能。荒谬的。这破坏了所有 IDE 工具,极大地增加了编码错误的可能性,并且通常使代码更难支持。+1 代表你的答案,-1 代表 Qt。 (2认同)

Mar*_* Ch 5

它与#ifdef 不同,因为决策都是在运行时发生的,但我有时会使用这种方法,它提供了类似的使用模式。

主程序

    QQmlApplicationEngine engine;
#ifdef DEMO_MODE
    engine.rootContext()->setContextProperty("DEMO_MODE", QVariant(true));
#else
    engine.rootContext()->setContextProperty("DEMO_MODE", QVariant(false));
#endif
    engine.load(QUrl("qrc:/ui/MainQmlFile.qml"));
Run Code Online (Sandbox Code Playgroud)

然后,从项目中的任何 .qml 文件

if (DEMO_MODE) {

} else {

}
Run Code Online (Sandbox Code Playgroud)