当从 QML 中的 Q_PROPERTY 访问时,QVariantList 变得嵌套
QVariantList becomes nested when accessed from Q_PROPERTY in QML
我在通过另一个 Q_GADGET 对象中的 Q_PROPERTY 访问由 Q_GADGET 对象组成的 QVariantLists 时遇到一个奇怪的问题。出于某种原因,当通过 属性 访问它们时,列表将自己嵌套在两个元素下,如下所示:
可变手表截图
这是一个小但有效的示例,它说明了我遇到的问题。
应用class:
#pragma once
#include <QObject>
#include "Data.h"
class App : public QObject
{
public:
explicit App( QObject* parent = nullptr );
public slots:
void getData() const;
signals:
void dataReady( const Data& data ) const;
private:
Q_OBJECT
};
#include "App.h"
App::App( QObject* parent )
{
}
void App::getData() const
{
emit dataReady( Data() );
}
数据class:
#pragma once
#include <QObject>
#include <QVariant>
#include "Stats.h"
class Data
{
public:
Data();
Data( const Data& data );
~Data() = default;
public slots:
QList< QVariant > getStats() const;
private:
Q_GADGET
Q_PROPERTY( QList< QVariant > stats READ getStats CONSTANT )
QList< QVariant > stats;
void fillStats();
};
Q_DECLARE_METATYPE(Data)
#include "Stats.h"
#include "Data.h"
Data::Data()
{
fillStats();
}
Data::Data( const Data& data ) :
stats{ data.stats }
{
}
void Data::fillStats()
{
for ( int i = 0; i < 10; i++ )
stats.append( QVariant::fromValue( Stats( i ) ) );
}
QList< QVariant > Data::getStats() const
{
return stats;
}
统计数据class:
#pragma once
#include <QObject>
class Stats
{
public:
Stats() = default;
Stats( int val );
Stats( const Stats& stats );
~Stats() = default;
public slots:
int getValue() const;
private:
Q_GADGET
Q_PROPERTY( int value READ getValue CONSTANT )
int value;
};
Q_DECLARE_METATYPE(Stats)
#include "Stats.h"
Stats::Stats(const Stats& stats) :
value{ stats.value }
{
}
Stats::Stats(int val) :
value{ val }
{
}
int Stats::getValue() const
{
return value;
}
main.cpp:
#include <QGuiApplication>
#include <QMetaType>
#include <QQmlApplicationEngine>
#include "App.h"
#include "Stats.h"
#include "Data.h"
int main( int argc, char* argv[] )
{
QGuiApplication app( argc, argv );
QQmlApplicationEngine engine;
qRegisterMetaType< Data >( "Data" );
qRegisterMetaType< Stats >( "Stats" );
qmlRegisterType< App >( "Test", 1, 0, "App" );
engine.load( QUrl( QStringLiteral( "qrc:/main.qml" ) ) );
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml:
import QtQuick 2.6
import QtQuick.Window 2.2
import Test 1.0
Window
{
visible: true
width: Screen.width
height: Screen.height
title: qsTr("Hello World")
Component.onCompleted: app.getData()
App
{
id: app
}
Connections
{
target: app
onDataReady: iterateThroughData( data )
}
function iterateThroughData( data )
{
for ( var i = 0; i < data.stats.length; i++ )
console.log( "broken here... somehow gets nested." );
}
}
现在,如果您在 main.qml 中的以下行放置断点:
for ( var i = 0; i < data.stats.length; i++ )
在手表 window 中,您将看到它如何以某种方式嵌套在另外两个单个元素列表中。
现在,如果我更改信号以发出列表而不是对象,则列表是完全正常的并且没有嵌套。
任何人曾经 运行 进入这个或看到任何明显的我可能会导致这个的事情吗?谢谢。抱歉,代码太多,这是我能做的最小的工作示例。
问题是由于想用下面一行代码复制列表造成的:
Data::Data( const Data& data ):
stats{data.stats}
// Is similar to stats << data.stats or stats.append(data.stats)
{
}
要在使用 {}
时成为 stats
QList,您正在添加一个项目,即现有统计数据的另一个统计数据,您必须做的是使用 copy constructor of QList:
Data::Data( const Data& data ):
stats(data.stats)
{
}
我在通过另一个 Q_GADGET 对象中的 Q_PROPERTY 访问由 Q_GADGET 对象组成的 QVariantLists 时遇到一个奇怪的问题。出于某种原因,当通过 属性 访问它们时,列表将自己嵌套在两个元素下,如下所示:
可变手表截图
这是一个小但有效的示例,它说明了我遇到的问题。
应用class:
#pragma once
#include <QObject>
#include "Data.h"
class App : public QObject
{
public:
explicit App( QObject* parent = nullptr );
public slots:
void getData() const;
signals:
void dataReady( const Data& data ) const;
private:
Q_OBJECT
};
#include "App.h"
App::App( QObject* parent )
{
}
void App::getData() const
{
emit dataReady( Data() );
}
数据class:
#pragma once
#include <QObject>
#include <QVariant>
#include "Stats.h"
class Data
{
public:
Data();
Data( const Data& data );
~Data() = default;
public slots:
QList< QVariant > getStats() const;
private:
Q_GADGET
Q_PROPERTY( QList< QVariant > stats READ getStats CONSTANT )
QList< QVariant > stats;
void fillStats();
};
Q_DECLARE_METATYPE(Data)
#include "Stats.h"
#include "Data.h"
Data::Data()
{
fillStats();
}
Data::Data( const Data& data ) :
stats{ data.stats }
{
}
void Data::fillStats()
{
for ( int i = 0; i < 10; i++ )
stats.append( QVariant::fromValue( Stats( i ) ) );
}
QList< QVariant > Data::getStats() const
{
return stats;
}
统计数据class:
#pragma once
#include <QObject>
class Stats
{
public:
Stats() = default;
Stats( int val );
Stats( const Stats& stats );
~Stats() = default;
public slots:
int getValue() const;
private:
Q_GADGET
Q_PROPERTY( int value READ getValue CONSTANT )
int value;
};
Q_DECLARE_METATYPE(Stats)
#include "Stats.h"
Stats::Stats(const Stats& stats) :
value{ stats.value }
{
}
Stats::Stats(int val) :
value{ val }
{
}
int Stats::getValue() const
{
return value;
}
main.cpp:
#include <QGuiApplication>
#include <QMetaType>
#include <QQmlApplicationEngine>
#include "App.h"
#include "Stats.h"
#include "Data.h"
int main( int argc, char* argv[] )
{
QGuiApplication app( argc, argv );
QQmlApplicationEngine engine;
qRegisterMetaType< Data >( "Data" );
qRegisterMetaType< Stats >( "Stats" );
qmlRegisterType< App >( "Test", 1, 0, "App" );
engine.load( QUrl( QStringLiteral( "qrc:/main.qml" ) ) );
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml:
import QtQuick 2.6
import QtQuick.Window 2.2
import Test 1.0
Window
{
visible: true
width: Screen.width
height: Screen.height
title: qsTr("Hello World")
Component.onCompleted: app.getData()
App
{
id: app
}
Connections
{
target: app
onDataReady: iterateThroughData( data )
}
function iterateThroughData( data )
{
for ( var i = 0; i < data.stats.length; i++ )
console.log( "broken here... somehow gets nested." );
}
}
现在,如果您在 main.qml 中的以下行放置断点:
for ( var i = 0; i < data.stats.length; i++ )
在手表 window 中,您将看到它如何以某种方式嵌套在另外两个单个元素列表中。
现在,如果我更改信号以发出列表而不是对象,则列表是完全正常的并且没有嵌套。
任何人曾经 运行 进入这个或看到任何明显的我可能会导致这个的事情吗?谢谢。抱歉,代码太多,这是我能做的最小的工作示例。
问题是由于想用下面一行代码复制列表造成的:
Data::Data( const Data& data ):
stats{data.stats}
// Is similar to stats << data.stats or stats.append(data.stats)
{
}
要在使用 {}
时成为 stats
QList,您正在添加一个项目,即现有统计数据的另一个统计数据,您必须做的是使用 copy constructor of QList:
Data::Data( const Data& data ):
stats(data.stats)
{
}