将对象从 c++ 发送到 qml。空闲内存呢?
Posted
技术标签:
【中文标题】将对象从 c++ 发送到 qml。空闲内存呢?【英文标题】:Send object from c++ to qml. What about free memory? 【发布时间】:2016-04-08 03:57:24 【问题描述】:有一个继承自 QAbstractListModel 的模型,我在 qml 中使用它。该模型的属性之一是参数,它们特定于该模型的元素类型。这是该类 TemperatureParam 的参数的一个元素,另一个是 DifrentParamType,第三个仍然是……如何将对象传递给 qml 并确保在使用后释放内存?下面的代码现在可以按我的需要运行,但在我看来它并不安全。
Param 类如此琐碎:
class QuickTemperatureParam : public QObject
Q_OBJECT
Q_PROPERTY(float param1 READ param1 WRITE setParam1)
//...
;
模型类(这就是我要问的):
class SectionsModel : public QAbstractListModel
//...
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override
//...
int type = getType( idx );
if (type == 1)
auto p = new QuickTemperatureParam( idx );
p->deleteLater(); // This is all right or no?
return qVariantFromValue(p);
else if (type == 2)
//...
;
QML 是这样的:
ListView
model: sectionsModel
delegate: Rectangle
color: model.statusColor
ItemDelegate
text: model.title
highlighted: ListView.isCurrentItem
onPressed:
switch ( model.type )
case SectionType.Temperature:
temperatureParam.openItem(model)
break;
case SectionType.Lighting:
lightingParam.open(model)
break;
Popup
id: temperatureParam
function openItem(model)
var p = model.param
params.itemAt(0).range.from = params.itemAt(1).range.from = p.min
params.itemAt(0).range.to = params.itemAt(1).range.to = p.max
params.itemAt(0).range.setValues( p.dayMin, p.dayMax )
params.itemAt(1).range.setValues( p.nightMin, p.nightMax )
open()
【问题讨论】:
【参考方案1】:根据documentation:
当数据从 C++ 传输到 QML 时,数据的所有权 始终使用 C++。此规则的例外是当 QObject 从显式 C++ 方法调用返回:在这种情况下,QML 引擎假定对象的所有权,除非该对象的所有权 对象已通过调用显式设置为保留在 C++ 中 QQmlEngine::setObjectOwnership() 与 QQmlEngine::CppOwnership 指定。
通常,应用程序不需要明确设置对象的所有权。如您所见here,默认情况下,由 QML 创建的对象具有javascriptOwnership
。
从 C++ 方法调用返回的对象也将设置为 JavaScriptOwnership
,但这仅适用于显式调用 Q_INVOKABLE
方法或槽。
因为方法data
不是显式的C++方法调用,你应该考虑将对象所有权设置为QQmlEngine::JavaScriptOwnership
调用setObjectOwnership()
所以,一般来说:
如果您希望 QML 销毁对象,请不要使用QQmlEngine::CppOwnership
。相关的数据将在适当的时候被删除(即在垃圾收集器发现没有更多对该值的实时引用之后)
QSharedPointer
可能不起作用。你有更多信息here。
【讨论】:
哇,我不知道。谢谢回复。但是我尝试了 setObjectOwnership,它对我的效果比 deleteLater 差得多。如果我离开 deleteLater 是否足够安全,如果 QQmlEngine 和我的模型是在同一个线程中创建的。退出函数 temperatureParam.openItem (QML) 后,我不再需要这个对象。或者该对象可能之前被删除? @lirik90 谢谢你!好吧,我没有说要删除deleteLater
代码行。对不起,如果我没有正确解释自己:(如果data
在temperatureParam.openItem
期间执行(我是对的吗?),那么我认为p
不会被删除,除非您将其所有权设置为QQmlEngine::JavaScriptOwnership
。
所以,为了安全起见,将new
对象传递给QML 时始终设置QQmlEngine::JavaScriptOwnership
是否合理,即使上述暗示QML 将获得所有权?在这种情况下,我会考虑这样做以使传输更清晰:template <typename T> T* TransferObjectOwnershipToJavaScript(std::unique_ptr<T> ptr) T* result = ptr.get(); QQmlEngine::setObjectOwnership(ptr.release(), QQmlEngine::JavaScriptOwnership); return result;
。以上是关于将对象从 c++ 发送到 qml。空闲内存呢?的主要内容,如果未能解决你的问题,请参考以下文章