Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Qt 6
  4. Collisions with custom QGraphicsItem that inherits from QObject
QtWS25 Last Chance

Collisions with custom QGraphicsItem that inherits from QObject

Scheduled Pinned Locked Moved Unsolved Qt 6
qt6collisionsqgraphicsitem
5 Posts 3 Posters 897 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    black_gay
    wrote on 7 May 2022, 20:56 last edited by black_gay 5 Jul 2022, 21:52
    #1

    I made QGraphicsItem (named "player") and a custom QGraphicsItem (named "customRect"), which inherits from QObject (because inside the class i use QTimer). Then, by using collidingItems(), i list all the items player collides with. The thing i dont understand is why, when collision with customRect occurs, the address returned by collidingItems() is different than customRect (shifted by 16 bytes). In my case address of customRect at creation is 0x1ca091c5450, and collidingItems() returns 0x1ca091c5460 (while when 2 non-custom QGraphicsItems collide, there is no such shift). Through trial and error i found out that Q_OBJECT macro shifts the address. So my question is, how do i prevent the shift or retrive the correct address from collidingItems()?

    My code is:

    //main:
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Game g;
        QTimer* timer = new QTimer(&g);
        QObject::connect(timer, &QTimer::timeout, &g, &Game::advance);
        timer->start(1000/3);
        return a.exec();
    }
     
    //Game header:
    class Game : public QGraphicsScene
    {
        Q_OBJECT
    public:
        explicit Game();
        void keyPressEvent(QKeyEvent *event);
        void advance();
    signals:
    private:
        QGraphicsRectItem* player;
        QGraphicsRectItem* rectItem;
        CustomRect* customRect;
        QGraphicsView* m_view;
    };
     
     
    //game cpp:
     
    #include "game.h"
    #include <QGraphicsItemGroup>
    #include <iostream>
     
    Game::Game()
    {
        player  = new QGraphicsRectItem();
        m_view = new QGraphicsView(this);
        m_view->setSceneRect(QRectF(0,0,800,600));
     
     
        this->setBackgroundBrush(Qt::black);
        m_view->setScene(this);
        m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        m_view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
        m_view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
        m_view->show();
     
        player->setRect(0,0,100,100);
        player->setBrush(Qt::red);
        player->setPos(400,300);
        player->setFocus();
     
     
        this->addItem(player);
     
        player->setZValue(10);
     
     
        player->setTransformOriginPoint(player->boundingRect().center());
     
        customRect = new CustomRect;
        customRect->setPos(400,300);
        this->addItem(customRect);
     
    }
     
     
    void Game::advance()
    {
        std::cout << "customRect: " <<  customRect << "\n";
     
        QList<QGraphicsItem*> list = player->collidingItems();
     
        for (int i = 0; i < list.size(); ++i) {
            std::cout << "i: " << list.at(i) << "\n";
        }
    }
     
    //customRect header:
    class CustomRect : public QObject, public QGraphicsItem
    {
        Q_OBJECT
    public:
        explicit CustomRect (QGraphicsItem *parent = nullptr);
     
        virtual QRectF 	boundingRect() const;
        virtual void 	paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
    private:
        QRectF rect;
    };
     
    //customRect cpp:
     
    CustomRect::CustomRect(QGraphicsItem *parent)  : QGraphicsItem{parent}
    {
        std::cout << "this: " << this << "\n";
        rect.setRect(0,0,100,100);
        std::cout << "rect: " << &rect << "\n";
     
    }
     
     
    QRectF CustomRect::boundingRect() const
    {
     
        return rect;
    }
     
    void CustomRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
       QPen towerPen(Qt::green, 3);
       painter->setPen(towerPen);
       painter->setRenderHint(QPainter::Antialiasing);
       painter->drawRect(rect);
     
    }
    
    C J 2 Replies Last reply 8 May 2022, 07:36
    0
    • B black_gay
      7 May 2022, 20:56

      I made QGraphicsItem (named "player") and a custom QGraphicsItem (named "customRect"), which inherits from QObject (because inside the class i use QTimer). Then, by using collidingItems(), i list all the items player collides with. The thing i dont understand is why, when collision with customRect occurs, the address returned by collidingItems() is different than customRect (shifted by 16 bytes). In my case address of customRect at creation is 0x1ca091c5450, and collidingItems() returns 0x1ca091c5460 (while when 2 non-custom QGraphicsItems collide, there is no such shift). Through trial and error i found out that Q_OBJECT macro shifts the address. So my question is, how do i prevent the shift or retrive the correct address from collidingItems()?

      My code is:

      //main:
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          Game g;
          QTimer* timer = new QTimer(&g);
          QObject::connect(timer, &QTimer::timeout, &g, &Game::advance);
          timer->start(1000/3);
          return a.exec();
      }
       
      //Game header:
      class Game : public QGraphicsScene
      {
          Q_OBJECT
      public:
          explicit Game();
          void keyPressEvent(QKeyEvent *event);
          void advance();
      signals:
      private:
          QGraphicsRectItem* player;
          QGraphicsRectItem* rectItem;
          CustomRect* customRect;
          QGraphicsView* m_view;
      };
       
       
      //game cpp:
       
      #include "game.h"
      #include <QGraphicsItemGroup>
      #include <iostream>
       
      Game::Game()
      {
          player  = new QGraphicsRectItem();
          m_view = new QGraphicsView(this);
          m_view->setSceneRect(QRectF(0,0,800,600));
       
       
          this->setBackgroundBrush(Qt::black);
          m_view->setScene(this);
          m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
          m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
          m_view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
          m_view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
          m_view->show();
       
          player->setRect(0,0,100,100);
          player->setBrush(Qt::red);
          player->setPos(400,300);
          player->setFocus();
       
       
          this->addItem(player);
       
          player->setZValue(10);
       
       
          player->setTransformOriginPoint(player->boundingRect().center());
       
          customRect = new CustomRect;
          customRect->setPos(400,300);
          this->addItem(customRect);
       
      }
       
       
      void Game::advance()
      {
          std::cout << "customRect: " <<  customRect << "\n";
       
          QList<QGraphicsItem*> list = player->collidingItems();
       
          for (int i = 0; i < list.size(); ++i) {
              std::cout << "i: " << list.at(i) << "\n";
          }
      }
       
      //customRect header:
      class CustomRect : public QObject, public QGraphicsItem
      {
          Q_OBJECT
      public:
          explicit CustomRect (QGraphicsItem *parent = nullptr);
       
          virtual QRectF 	boundingRect() const;
          virtual void 	paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
      private:
          QRectF rect;
      };
       
      //customRect cpp:
       
      CustomRect::CustomRect(QGraphicsItem *parent)  : QGraphicsItem{parent}
      {
          std::cout << "this: " << this << "\n";
          rect.setRect(0,0,100,100);
          std::cout << "rect: " << &rect << "\n";
       
      }
       
       
      QRectF CustomRect::boundingRect() const
      {
       
          return rect;
      }
       
      void CustomRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
      {
         QPen towerPen(Qt::green, 3);
         painter->setPen(towerPen);
         painter->setRenderHint(QPainter::Antialiasing);
         painter->drawRect(rect);
       
      }
      
      C Offline
      C Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 8 May 2022, 07:36 last edited by
      #2

      @black_gay said in Collisions with custom QGraphicsItem that inherits from QObject:

      public QObject, public QGraphicsItem

      So my question is, how do i prevent the shift or retrive the correct address from collidingItems()?

      You can't - or invent something other than c++
      Since QObject needs some memory, esp. when you add functions for QObject the addresses differ.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      1
      • B black_gay
        7 May 2022, 20:56

        I made QGraphicsItem (named "player") and a custom QGraphicsItem (named "customRect"), which inherits from QObject (because inside the class i use QTimer). Then, by using collidingItems(), i list all the items player collides with. The thing i dont understand is why, when collision with customRect occurs, the address returned by collidingItems() is different than customRect (shifted by 16 bytes). In my case address of customRect at creation is 0x1ca091c5450, and collidingItems() returns 0x1ca091c5460 (while when 2 non-custom QGraphicsItems collide, there is no such shift). Through trial and error i found out that Q_OBJECT macro shifts the address. So my question is, how do i prevent the shift or retrive the correct address from collidingItems()?

        My code is:

        //main:
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
            Game g;
            QTimer* timer = new QTimer(&g);
            QObject::connect(timer, &QTimer::timeout, &g, &Game::advance);
            timer->start(1000/3);
            return a.exec();
        }
         
        //Game header:
        class Game : public QGraphicsScene
        {
            Q_OBJECT
        public:
            explicit Game();
            void keyPressEvent(QKeyEvent *event);
            void advance();
        signals:
        private:
            QGraphicsRectItem* player;
            QGraphicsRectItem* rectItem;
            CustomRect* customRect;
            QGraphicsView* m_view;
        };
         
         
        //game cpp:
         
        #include "game.h"
        #include <QGraphicsItemGroup>
        #include <iostream>
         
        Game::Game()
        {
            player  = new QGraphicsRectItem();
            m_view = new QGraphicsView(this);
            m_view->setSceneRect(QRectF(0,0,800,600));
         
         
            this->setBackgroundBrush(Qt::black);
            m_view->setScene(this);
            m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
            m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
            m_view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
            m_view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
            m_view->show();
         
            player->setRect(0,0,100,100);
            player->setBrush(Qt::red);
            player->setPos(400,300);
            player->setFocus();
         
         
            this->addItem(player);
         
            player->setZValue(10);
         
         
            player->setTransformOriginPoint(player->boundingRect().center());
         
            customRect = new CustomRect;
            customRect->setPos(400,300);
            this->addItem(customRect);
         
        }
         
         
        void Game::advance()
        {
            std::cout << "customRect: " <<  customRect << "\n";
         
            QList<QGraphicsItem*> list = player->collidingItems();
         
            for (int i = 0; i < list.size(); ++i) {
                std::cout << "i: " << list.at(i) << "\n";
            }
        }
         
        //customRect header:
        class CustomRect : public QObject, public QGraphicsItem
        {
            Q_OBJECT
        public:
            explicit CustomRect (QGraphicsItem *parent = nullptr);
         
            virtual QRectF 	boundingRect() const;
            virtual void 	paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
        private:
            QRectF rect;
        };
         
        //customRect cpp:
         
        CustomRect::CustomRect(QGraphicsItem *parent)  : QGraphicsItem{parent}
        {
            std::cout << "this: " << this << "\n";
            rect.setRect(0,0,100,100);
            std::cout << "rect: " << &rect << "\n";
         
        }
         
         
        QRectF CustomRect::boundingRect() const
        {
         
            return rect;
        }
         
        void CustomRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
        {
           QPen towerPen(Qt::green, 3);
           painter->setPen(towerPen);
           painter->setRenderHint(QPainter::Antialiasing);
           painter->drawRect(rect);
         
        }
        
        J Offline
        J Offline
        JonB
        wrote on 8 May 2022, 07:52 last edited by
        #3

        @black_gay said in Collisions with custom QGraphicsItem that inherits from QObject:

        I made QGraphicsItem (named "player") and a custom QGraphicsItem (named "customRect"), which inherits from QObject (because inside the class i use QTimer).
        class CustomRect : public QObject, public QGraphicsItem

        Apart from the answer @Christian-Ehrlicher has given to the question you ask. The above is what QGraphicsObject Class does:

        The QGraphicsObject class provides a base class for all graphics items that require signals, slots and properties

        and is what you should use in preference to rolling your own.

        C 1 Reply Last reply 8 May 2022, 08:57
        0
        • J JonB
          8 May 2022, 07:52

          @black_gay said in Collisions with custom QGraphicsItem that inherits from QObject:

          I made QGraphicsItem (named "player") and a custom QGraphicsItem (named "customRect"), which inherits from QObject (because inside the class i use QTimer).
          class CustomRect : public QObject, public QGraphicsItem

          Apart from the answer @Christian-Ehrlicher has given to the question you ask. The above is what QGraphicsObject Class does:

          The QGraphicsObject class provides a base class for all graphics items that require signals, slots and properties

          and is what you should use in preference to rolling your own.

          C Offline
          C Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 8 May 2022, 08:57 last edited by
          #4

          @JonB But it will behave exactly as his class wrt to the pointers:

          class Q_WIDGETS_EXPORT QGraphicsObject : public QObject, public QGraphicsItem

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          J 1 Reply Last reply 8 May 2022, 09:40
          1
          • C Christian Ehrlicher
            8 May 2022, 08:57

            @JonB But it will behave exactly as his class wrt to the pointers:

            class Q_WIDGETS_EXPORT QGraphicsObject : public QObject, public QGraphicsItem

            J Offline
            J Offline
            JonB
            wrote on 8 May 2022, 09:40 last edited by JonB 5 Aug 2022, 09:41
            #5

            @Christian-Ehrlicher said in Collisions with custom QGraphicsItem that inherits from QObject:

            @JonB But it will behave exactly as his class wrt to the pointers:

            Absolutely true! Hence I said

            Apart from the answer @Christian-Ehrlicher has given to the question you ask.

            This is just a suggestion for if OP does want equivalent for the class CustomRect : public QObject, public QGraphicsItem. Not that it will change any behaviour wrt to pointers question.

            1 Reply Last reply
            0

            1/5

            7 May 2022, 20:56

            • Login

            • Login or register to search.
            1 out of 5
            • First post
              1/5
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved