【发布时间】: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<QString> 将作为组合框的模型。我的猜测是 QList<QString> 被转换为 JavaScript array 字符串,然后转换回 ComboBox 的模型属性需要的任何 C++ 部分。毕竟,该属性接受 JavaScript 中定义的字符串数组。但是,似乎在将QuickSerialPortInformer 的属性分配给ComboBox 的model 时,没有进行这样的编组。正如 cmets 中所指出的,只有一些 C++ 类型可以用作 QtQuick 视图的模型。其中之一是QStringList,我现在正在使用。
ComboBox {
id: portSelector
model: serialPortInformer.portselectionmodel
}
我的问题是 SerialPortInformer 在 qml 上下文中是未知的。我怀疑我用来注册对象的上下文对于我正在使用engine.load() 执行的脚本是不可见的。我试图颠倒load() 和setContextProperty() 的顺序无济于事。我错过了什么?
按照 cmets 和文档中的建议将 SerialPortInformer 重命名为 serialPortInformer 后,出现了另一个问题。 serialPortInformer 是 QML 中值 true 的 boolean,而不是预期的对象。
我能够解决“布尔”之谜,直到我能够使我的用例工作。答案是我的SerialPortInformer::getInstance() 正在返回一个指向const 的指针。一旦我删除了 const-qualifier serialPortInformer 是对象类型并暴露了所需的属性。我能想到为什么首先编译它的唯一原因是使用非explicit 构造函数调用了该方法的const QVariant & 重载。所以我的自我说明是:永远不要在 QML 上下文中注册指向常量 QObjects 的指针
【问题讨论】:
-
如果您使用小写名称会发生什么情况:
serialPortInformer? -
我之前也有过这样的情况,然后重试了。问题仍然存在。
serialPortInformer没有出现在 qml 调试窗口中。我希望它与mainWindow处于同一水平 -
项目本身可见你的
ComboBox不能分派值的问题。尝试将QList<QString>替换为QStringList。有关更多信息,请参阅this 页面。特别是这个注释:A C++ model class can be defined as a QStringList, a QObjectList or a QAbstractItemModel。这里没有QList<QString>。 -
另外
portselectionmodel应该被声明为 NOTIFYable 属性 -
@everclear 如果属性的内容没有改变,使用
CONSTANT而不是NOTIFY