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 893 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 last edited by black_gay
    #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);
     
    }
    
    Christian EhrlicherC JonBJ 2 Replies Last reply
    0
    • B black_gay

      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);
       
      }
      
      Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 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

        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);
         
        }
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on 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.

        Christian EhrlicherC 1 Reply Last reply
        0
        • JonBJ JonB

          @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.

          Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 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

          JonBJ 1 Reply Last reply
          1
          • Christian EhrlicherC Christian Ehrlicher

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

            class Q_WIDGETS_EXPORT QGraphicsObject : public QObject, public QGraphicsItem

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #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

            • Login

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