【问题标题】:Setting a Qml Context Property in the Qt5.7 QtQuick2 application template在 Qt5.7 QtQuick2 应用程序模板中设置 Qml 上下文属性
【发布时间】:2016-12-30 21:24:08
【问题描述】:

我的目标是使用(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&lt;QString&gt; 将作为组合框的模型。我的猜测是 QList&lt;QString&gt; 被转换为 JavaScript array 字符串,然后转换回 ComboBox 的模型属性需要的任何 C++ 部分。毕竟,该属性接受 JavaScript 中定义的字符串数组。但是,似乎在将QuickSerialPortInformer 的属性分配给ComboBoxmodel 时,没有进行这样的编组。正如 cmets 中所指出的,只有一些 C++ 类型可以用作 QtQuick 视图的模型。其中之一是QStringList,我现在正在使用。

ComboBox {
    id: portSelector
    model: serialPortInformer.portselectionmodel
}

我的问题是 SerialPortInformer 在 qml 上下文中是未知的。我怀疑我用来注册对象的上下文对于我正在使用engine.load() 执行的脚本是不可见的。我试图颠倒load()setContextProperty() 的顺序无济于事。我错过了什么?

按照 cmets 和文档中的建议将 SerialPortInformer 重命名为 serialPortInformer 后,出现了另一个问题。 serialPortInformer 是 QML 中值 trueboolean,而不是预期的对象。

我能够解决“布尔”之谜,直到我能够使我的用例工作。答案是我的SerialPortInformer::getInstance() 正在返回一个指向const 的指针。一旦我删除了 const-qualifier serialPortInformer 是对象类型并暴露了所需的属性。我能想到为什么首先编译它的唯一原因是使用非explicit 构造函数调用了该方法的const QVariant &amp; 重载。所以我的自我说明是:永远不要在 QML 上下文中注册指向常量 QObjects 的指针

【问题讨论】:

  • 如果您使用小写名称会发生​​什么情况:serialPortInformer?
  • 我之前也有过这样的情况,然后重试了。问题仍然存在。 serialPortInformer 没有出现在 qml 调试窗口中。我希望它与mainWindow 处于同一水平
  • 项目本身可见你的ComboBox不能分派值的问题。尝试将QList&lt;QString&gt; 替换为QStringList。有关更多信息,请参阅this 页面。特别是这个注释:A C++ model class can be defined as a QStringList, a QObjectList or a QAbstractItemModel。这里没有QList&lt;QString&gt;
  • 另外 portselectionmodel 应该被声明为 NOTIFYable 属性
  • @everclear 如果属性的内容没有改变,使用CONSTANT而不是NOTIFY

标签: qt qml


【解决方案1】:

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

#include <QList>
#include <QObject>

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

ma​​in.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();
}

【讨论】:

    【解决方案2】:

    首先,按如下方式实现您的Q_PROPERTY (see documentation):

    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
    }
    

    应该可以,我以前用过这个实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多