在Qt5.7 QtQuick2应用程序模板中设置Qml上下文属性

时间:2016-12-29 10:38:44

标签: qt qml

我的目标是使用(Windows)计算机上可用的串行端口填充组合框。我为QSerialPortInfo创建了一个包装器,我想将其作为QML根上下文属性发布。我使用QtQuick2应用程序模板作为起点。

#include <QList>
#include <QObject>

class QuickSerialPortInformer : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<QString> portselectionmodel READ portselectionmodel CONST)

public:
    static const QuickSerialPortInformer *getInstance();

    QList<QString> portselectionmodel() const;

protected:
    QuickSerialPortInformer();

private:
    static const QuickSerialPortInformer *Instance;
};

#endif // QUICKSERIALPORTINFORMER_H

我注册了这样的对象:

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    /* here */ engine.rootContext()->setContextProperty("serialPortInformer", QuickSerialPortInformer::getInstance());
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    return app.exec();
}

属性返回的QList<QString>应作为组合框的模型。我的猜测是QList<QString>转换为JavaScript array字符串,然后转换回ComboBox模型属性所需的C ++部分。毕竟,该属性接受JavaScript中定义的字符串数组。但是,似乎在将QuickSerialPortInformer的属性分配给model的{​​{1}}时,不会进行此类编组操作。正如评论中指出的,只有一些C ++类型可以用作QtQuick视图的模型。其中一个是ComboBox,我现在正在使用它。

QStringList

我的问题是qml上下文中ComboBox { id: portSelector model: serialPortInformer.portselectionmodel } 未知。我怀疑用于注册对象的上下文对于我使用SerialPortInformer执行的脚本是不可见的。我试图颠倒engine.load()load()的顺序无济于事。我错过了什么?

根据评论和文档中的建议将setContextProperty()重命名为SerialPortInformer后,会出现另一个问题。 serialPortInformer是QML中值serialPortInformer的{​​{1}},而不是预期的对象。

我能够解决&#34; boolean&#34; -mystery到我能够使我的用例工作的程度。答案是我的boolean正在返回指向true的指针。一旦我删除了SerialPortInformer::getInstance() - 限定符const类型为object并公开了所需的属性。我能想到为什么首先编译的唯一原因是使用非const构造函数调用了方法的serialPortInformer重载。所以我的自我记录是:永远不要在QML上下文中注册指向常量const QVariant &的指针

2 个答案:

答案 0 :(得分:1)

由于您只想阅读QStringList,只需将QStringList作为Q_INVOKABLE方法的返回类型。此外,我没有看到您创建一个QuickSerialPortInformer的对象,您可能在原始代码中创建了该对象。总结你的代码应该是这样的,

#include <QList>
#include <QObject>

class QuickSerialPortInformer : public QObject
{
    Q_OBJECT
    Q_INVOKABLE QStringList portselectionmodel();
    ....
};

<强>的main.cpp

int main(int argc, char *argv[])
{
    ...
    QuickSerialPortInformer portInformer;
    QQmlApplicationEngine engine; 
    engine.rootContext()->setContextProperty("serialPortInformer",&portInformer);
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    return app.exec();
}

答案 1 :(得分:0)

首先,按照以下方式(see documentation)实施Q_PROPERTY

Q_PROPERTY(QStringList portSelectionModel READ portSelectionModel WRITE setPortSelectionModel NOTIFY portSelectionModelChanged)

不确定为什么你的单身人士不工作,但试着像这样实施:

public:
static QuickSerialPortInformer& Instance()
{
    static QuickSerialPortInformer instance; 
    return instance;
}
~QuickSerialPortInformer()=default;

private:
QuickSerialPortInformer()=default;
QuickSerialPortInformer(QuickSerialPortInformer const&)=delete;
void operator = (QuickSerialPortInformer const&)=delete;

在你的main.cpp上:

QQmlContext* quickSerialPortInformerCtx = engine.rootContext();
quickSerialPortInformerCtx->setContextProperty("quickserialportinformer", &QuickSerialPortInformer::Instance());

在你的qml上:

ComboBox {
    model: quickserialportinformer.portSelectionModel
}

它应该有用,我之前使用过这个实现。