当从QML中的Q_PROPERTY访问时,QVariantList变为嵌套

时间:2018-01-25 17:50:19

标签: c++ qt qml qt5 qt-signals

我在通过另一个Q_GADGET对象中的Q_PROPERTY访问由Q_GADGET对象组成的QVariantLists时遇到了一个奇怪的问题。出于某种原因,当通过属性访问它们时,列表将自己嵌入两个元素中,如下所示:

可变观看截图

这是一个小但有效的例子,说明了我遇到的问题。

App类:

#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() );
}

数据类:

#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;
}

统计类:

#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++ )

在观察窗口中,您将看到它是如何嵌套在另外两个单个元素列表中的。

现在,如果我更改信号以发出列表而不是对象,则列表完全正常而不是嵌套。

任何人遇到这种情况或看到任何明显的事情我可能会做到这一点?谢谢。很抱歉这么多代码,这是我能做的最小的工作示例。

1 个答案:

答案 0 :(得分:0)

问题是由于想要使用以下代码行复制列表而引起的:

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)
{
}