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

时间:2016-11-14 08:24:58

标签: qt macros qml qt5

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

6 个答案:

答案 0 :(得分:3)

如果您可以将这些部件重构为自己的组件,您有两种选择:

  1. File selectors
  2. Loader
  3. 第一个选项可能比使用#ifdef更接近C风格Loader宏,因为它在文件级别工作。但是,只要您不过度使用Loader(例如,作为大视图中的代理人),他们都应该做好工作。

答案 1 :(得分:1)

#ifdef是一个预处理器指令,即在C或C ++编译器看到代码之前在构建时处理的内容。 您可以使用您选择的文本操作语言执行相同操作,在构建时处理QML文件,然后再处理它们,例如:由Qt资源编译器。

答案 2 :(得分:1)

它与#ifdef不同,因为所有决策都是在运行时进行的,但是我有时会使用这种方法,它给出了相似的用法模式。

main.cpp

    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"));

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

if (DEMO_MODE) {

} else {

}

答案 3 :(得分:0)

您也可以使用带有函数

的类DebugC
Q_INVOKABLE bool isDebuggingEnable()
{
  #ifdef QT_DEBUG
    return true;
  #else
    return false;
  #endif
}

然后在qml

中注册此类
viewer->rootContext()->setContextProperty("stName", DebugCObj)

现在您可以轻松调用stName.isDebuggingEnable()方法来检查QML文件中是否启用调试。这只是一个技巧

答案 4 :(得分:0)

QML在运行时不是编译而是解释,因此预处理器指令不能直接用于 通过QML。 但这不是一个限制,因为可以从c ++方面向QML引入属性。因此,指令可以放在C ++端为这些属性配置,同时基于这些属性的决策制定,正常if/then, Javascript可用于QML方面。

答案 5 :(得分:0)

正如@Mark所建议的那样,可以在QML中使用上下文属性来在运行时确定是否启用了某些宏,但是当您需要基于此决定实例化对象时,他提供的示例并未解决这种情况。 ,但仅涵盖在代码块内的情况。因此,我将提供我所做工作的完整示例。

就我而言,我仅在编译时定义了宏时才将类暴露给QML:

main.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

然后在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
    }
}

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