Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QGraphicscene中元素的迭代器_C++_Qt_Iterator_Qgraphicsitem_Qgraphicsscene - Fatal编程技术网

C++ QGraphicscene中元素的迭代器

C++ QGraphicscene中元素的迭代器,c++,qt,iterator,qgraphicsitem,qgraphicsscene,C++,Qt,Iterator,Qgraphicsitem,Qgraphicsscene,我有一个qgraphicscene,其中包含自定义对象(以QGraphicsItem为基类)。我可以通过以下方式检索这些对象: foreach (QGraphicsItem* item, items()) { if (item->type() == CustomItem::Type) qgraphicsitem_cast<CustomItem*>(item).doStuff(...); } 我希望避免手动存储指向这些对象的指针(例如在向量中),因为这涉

我有一个
qgraphicscene
,其中包含自定义对象(以
QGraphicsItem
为基类)。我可以通过以下方式检索这些对象:

foreach (QGraphicsItem* item, items()) {
    if (item->type() == CustomItem::Type)
        qgraphicsitem_cast<CustomItem*>(item).doStuff(...);
}

我希望避免手动存储指向这些对象的指针(例如在向量中),因为这涉及到删除对象时的额外簿记,这很容易出错。这样的迭代器是什么样子的。如何实现
custom_items()
方法?

可以很容易地强制来自的布局迭代器适配器在场景项上工作:

// https://github.com/KubaO/stackoverflown/tree/master/questions/scene-iterator-adapter-32567814
#include <QGraphicsScene>
#include <QList>
#include <QDebug>
#include <utility>

template<class> class IterableSceneAdapter;

template<typename IT>
class ItemListIterator {
   const QList<QGraphicsItem*> * m_items;
   int m_index;
   friend class IterableSceneAdapter<IT>;
   ItemListIterator(const QList<QGraphicsItem*> * items, int dir) :
      m_items(items), m_index(dir>0 ? -1 : items->count()) {
      if (dir > 0) ++*this;
   }
   friend QDebug operator<<(QDebug dbg, const ItemListIterator & it) {
      return dbg << (it.m_items->isEmpty() ? nullptr : it.m_items->first()->scene())
                 << it.m_index;
   }
   friend void swap(ItemListIterator& a, ItemListIterator& b) {
      using std::swap;
      swap(a.m_items, b.m_items);
      swap(a.m_index, b.m_index);
   }
   template <typename T> T item_cast(QGraphicsItem* item) {
      // use qgraphicsitem_cast if you don't have RTTI enabled
      return dynamic_cast<T>(item);
   }
public:
   ItemListIterator() : m_index(0) {}
   ItemListIterator(const ItemListIterator & o) :
      m_items(o.m_items), m_index(o.m_index) {}
   ItemListIterator(ItemListIterator && o) { swap(*this, o); }
   ItemListIterator & operator=(ItemListIterator o) {
      swap(*this, o);
      return *this;
   }
   IT * operator*() const { return static_cast<IT*>(m_items->at(m_index)); }
   const ItemListIterator & operator++() {
      while (++m_index < m_items->count() && !item_cast<IT*>(m_items->at(m_index)));
      return *this;
   }
   ItemListIterator operator++(int) {
      ItemListIterator temp{*this};
      ++*this;
      return temp;
   }
   const ItemListIterator & operator--() {
      while (!item_cast<IT*>(m_items->at(--m_index)) && m_index > 0);
      return *this;
   }
   ItemListIterator operator--(int) {
      ItemListIterator temp(*this);
      --*this;
      return temp;
   }
   bool operator==(const ItemListIterator & o) const { return m_index == o.m_index; }
   bool operator!=(const ItemListIterator & o) const { return m_index != o.m_index; }
};

template <class IT = QGraphicsItem>
class IterableSceneAdapter {
   const QList<QGraphicsItem*> m_items;
public:
   typedef ItemListIterator<IT> iterator;
   typedef iterator const_iterator;
   IterableSceneAdapter(QGraphicsScene * scene) : m_items(scene->items()) {}
   const_iterator begin() const { return const_iterator(&m_items, 1); }
   const_iterator end() const { return const_iterator(&m_items, -1); }
   const_iterator cbegin() const { return const_iterator(&m_items, 1); }
   const_iterator cend() const { return const_iterator(&m_items, -1); }
};

template <class IT = QGraphicsItem>
class ConstIterableSceneAdapter : public IterableSceneAdapter<const IT> {
public:
   ConstIterableSceneAdapter(const QGraphicsScene * scene) :
      IterableSceneAdapter<const IT>(const_cast<QGraphicsScene*>(scene)) {}
};
//https://github.com/KubaO/stackoverflown/tree/master/questions/scene-iterator-adapter-32567814
#包括
#包括
#包括
#包括
模板类ITerableCenedapter;
模板
类ItemListIterator{
const QList*m_项目;
int m_指数;
朋友级无障碍阅读;
ItemListIterator(常量QList*items,int dir):
m_项(items),m_索引(dir>0?-1:items->count()){
如果(dir>0)+*这个;
}
friend QDebug运算符scene())
// https://github.com/KubaO/stackoverflown/tree/master/questions/scene-iterator-adapter-32567814
#include <QGraphicsScene>
#include <QList>
#include <QDebug>
#include <utility>

template<class> class IterableSceneAdapter;

template<typename IT>
class ItemListIterator {
   const QList<QGraphicsItem*> * m_items;
   int m_index;
   friend class IterableSceneAdapter<IT>;
   ItemListIterator(const QList<QGraphicsItem*> * items, int dir) :
      m_items(items), m_index(dir>0 ? -1 : items->count()) {
      if (dir > 0) ++*this;
   }
   friend QDebug operator<<(QDebug dbg, const ItemListIterator & it) {
      return dbg << (it.m_items->isEmpty() ? nullptr : it.m_items->first()->scene())
                 << it.m_index;
   }
   friend void swap(ItemListIterator& a, ItemListIterator& b) {
      using std::swap;
      swap(a.m_items, b.m_items);
      swap(a.m_index, b.m_index);
   }
   template <typename T> T item_cast(QGraphicsItem* item) {
      // use qgraphicsitem_cast if you don't have RTTI enabled
      return dynamic_cast<T>(item);
   }
public:
   ItemListIterator() : m_index(0) {}
   ItemListIterator(const ItemListIterator & o) :
      m_items(o.m_items), m_index(o.m_index) {}
   ItemListIterator(ItemListIterator && o) { swap(*this, o); }
   ItemListIterator & operator=(ItemListIterator o) {
      swap(*this, o);
      return *this;
   }
   IT * operator*() const { return static_cast<IT*>(m_items->at(m_index)); }
   const ItemListIterator & operator++() {
      while (++m_index < m_items->count() && !item_cast<IT*>(m_items->at(m_index)));
      return *this;
   }
   ItemListIterator operator++(int) {
      ItemListIterator temp{*this};
      ++*this;
      return temp;
   }
   const ItemListIterator & operator--() {
      while (!item_cast<IT*>(m_items->at(--m_index)) && m_index > 0);
      return *this;
   }
   ItemListIterator operator--(int) {
      ItemListIterator temp(*this);
      --*this;
      return temp;
   }
   bool operator==(const ItemListIterator & o) const { return m_index == o.m_index; }
   bool operator!=(const ItemListIterator & o) const { return m_index != o.m_index; }
};

template <class IT = QGraphicsItem>
class IterableSceneAdapter {
   const QList<QGraphicsItem*> m_items;
public:
   typedef ItemListIterator<IT> iterator;
   typedef iterator const_iterator;
   IterableSceneAdapter(QGraphicsScene * scene) : m_items(scene->items()) {}
   const_iterator begin() const { return const_iterator(&m_items, 1); }
   const_iterator end() const { return const_iterator(&m_items, -1); }
   const_iterator cbegin() const { return const_iterator(&m_items, 1); }
   const_iterator cend() const { return const_iterator(&m_items, -1); }
};

template <class IT = QGraphicsItem>
class ConstIterableSceneAdapter : public IterableSceneAdapter<const IT> {
public:
   ConstIterableSceneAdapter(const QGraphicsScene * scene) :
      IterableSceneAdapter<const IT>(const_cast<QGraphicsScene*>(scene)) {}
};
int main(int argc, char ** argv) {
   QApplication app(argc, argv);
   tests();
   QGraphicsScene s;
   QGraphicsLineItem b1, b3;
   QGraphicsEllipseItem b2;

   s.addItem(&b1);
   s.addItem(&b2);
   s.addItem(&b3);

   // Iterate all item types as constant items
   qDebug() << "all, range-for";
   for (auto item : ConstIterableSceneAdapter<>(&s)) qDebug() << item;
   qDebug() << "all, Q_FOREACH";
   Q_FOREACH (const QGraphicsItem * item, ConstIterableSceneAdapter<>(&s)) qDebug() << item;

   // Iterate ellipses only
   qDebug() << "ellipses, range-for";
   for (auto item : IterableSceneAdapter<QGraphicsEllipseItem>(&s)) qDebug() << item;
   qDebug() << "ellipses, Q_FOREACH";
   Q_FOREACH (QGraphicsEllipseItem * item, IterableSceneAdapter<QGraphicsEllipseItem>(&s)) qDebug() << item;
}
#include <QtWidgets>

void tests() {
   QGraphicsScene s;
   QGraphicsLineItem b1, b3;
   QGraphicsEllipseItem b2;

   IterableSceneAdapter<> s0{&s};
   auto i0 = s0.begin();
   qDebug() << i0; Q_ASSERT(i0 == s0.begin() && i0 == s0.end());

   s.addItem(&b1);
   s.addItem(&b2);
   s.addItem(&b3);

   IterableSceneAdapter<> s1{&s};
   auto i1 = s1.begin();
         qDebug() << i1; Q_ASSERT(i1 == s1.begin() && i1 != s1.end());
   ++i1; qDebug() << i1; Q_ASSERT(i1 != s1.begin() && i1 != s1.end());
   ++i1; qDebug() << i1; Q_ASSERT(i1 != s1.begin() && i1 != s1.end());
   ++i1; qDebug() << i1; Q_ASSERT(i1 != s1.begin() && i1 == s1.end());
   --i1; qDebug() << i1; Q_ASSERT(i1 != s1.begin() && i1 != s1.end());
   --i1; qDebug() << i1; Q_ASSERT(i1 != s1.begin() && i1 != s1.end());
   --i1; qDebug() << i1; Q_ASSERT(i1 == s1.begin() && i1 != s1.end());

   IterableSceneAdapter<QGraphicsEllipseItem> s2{&s};
   auto i2 = s2.begin();
         qDebug() << i2; Q_ASSERT(i2 == s2.begin() && i2 != s2.end());
   ++i2; qDebug() << i2; Q_ASSERT(i2 != s2.begin() && i2 == s2.end());
   --i2; qDebug() << i2; Q_ASSERT(i2 == s2.begin() && i2 != s2.end());
}