我需要关闭QML代码的某些部分,因为此代码是为演示目的而完成的,并且将在最终版本中删除。但是该产品将长时间与这些演示功能一起使用,因此我不能使用具有演示功能的单独分支,并且不断将所有新功能合并到该分支 - 这只是不方便。因此,运行此代码很好,但在需要时可以轻松关闭和/或删除。在C和C ++中,我使用ifdef
宏,但是可以在QML中执行相同的操作吗?
答案 0 :(得分: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)
您也可以使用带有函数
的类DebugCQ_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的source
或sourceComponent
属性中对其进行引用,但是我不确定,因为没有确定是否可以静态检查此组件(如果是我的情况)是否SmtpClient
类型可用