Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicsScene casting to derived class failed
Forum Updated to NodeBB v4.3 + New Features

QGraphicsScene casting to derived class failed

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 3 Posters 1.9k Views 1 Watching
  • 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.
  • TGVFT Offline
    TGVFT Offline
    TGVF
    wrote on last edited by
    #1

    My code is implementing subclasses of QGraphicsScene and QGraphicsItem in order to define some additional members.
    In my MainWindow , a QGraphicsPG object (subclass of QGraphicsItem) is constructed and added to the GraphicsScenePG object (subclass of QGraphicsScene).
    Then, a QGraphicsPG function compute() is called and need to access some members of GraphicsScenePG , but I was not able to cast the scene() pointer of type QGraphicsScene to the subclass pointer of type QGraphicsPG .
    I tried:

    • implicit or explicit cast: compilation error

    • static_cast and dynamic cast: both compile OK but fail during execution

    • reinterpret_cast: I did not try this quite dangerous operator...

    Here below my (simplified) code with the dynamic_cast attempt:

    // class GraphicsScenePG (header)
    #include <QGraphicsScene>
    class GraphicsScenePG : public QGraphicsScene
    {
    public:
        int nbMax ;
        GraphicsScenePG();
    }
    // class GraphicsScenePG (implementation)
    #include "GraphicsScenePG.h"
    GraphicsScenePG::GraphicsScenePG() : QGraphicsScene()  {    nbMax= 1 ;  }
    
    // class QGraphicsPG (header)
    #include <QGraphicsItem>
    class PG_Qt_MainWindow ;
    class QGraphicsPG : public QGraphicsItem
    {
    public:
        QGraphicsPG( QGraphicsItem *parent = 0 );
        ~QGraphicsPG();
        QRectF boundingRect() const ;
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                       QWidget *widget) ;
       void compute() ;
    }
    // class QGraphicsPG (implementation)
    #include <QtGui>
    #include "qgraphicspg.h"
    #include "pg_qt_mainwindow.h"
    QGraphicsPG::QGraphicsPG(QGraphicsItem *parent) : QGraphicsItem(parent)
    {
    //...
    }
    void QGraphicsPG::compute() {
        GraphicsScenePG *scene= (dynamic_cast<GraphicsScenePG*>(this->scene()) ) ; // cast failed!
        qDebug()<<"casted pointer="<<scene ;
    } 
    
    // class PG_Qt_MainWindow (header)
    #include <QMainWindow>
    #include "GraphicsScenePG.h"
    namespace Ui {  class PG_Qt_MainWindow; }
    class PG_Qt_MainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        explicit PG_Qt_MainWindow(QWidget *parent = 0);
        ~PG_Qt_MainWindow();
    private slots:
         void PG_Qt_MainWindow::on_actionDummy_triggered();
    private:
        Ui::PG_Qt_MainWindow *ui;
        GraphicsScenePG scene ; 
    };
    // class PG_Qt_MainWindow (implementation)
    #include "pg_qt_mainwindow.h"
    #include "ui_pg_qt_mainwindow.h"
    #include <QtGui>
    
    PG_Qt_MainWindow::PG_Qt_MainWindow(QWidget *parent) :
        QMainWindow(parent), 
        ui(new Ui::PG_Qt_MainWindow) ,
        scene() 
    {
        ui->setupUi(this);
        ui->graphicsView->setScene(&scene);
        ui->graphicsView->show() ;
        qDebug()<<"nbMax="<<scene.nbMax ; // OK so far!
    }
       void PG_Qt_MainWindow::on_actionDummy_triggered();
    {
                QGraphicsPG* item= new QGraphicsPG(0) ;
                scene.addItem(item);
               item.compute() ;
    }
    

    Execution gives:

    casted pointer= QObject(0x0)
    

    Trying to access the nbMax member from this incorrect pointer (null pointer?) crashes the execution.
    Of course, I could circumvent the issue e.g. passing the scene pointer of type GraphicsScenePG directly as an argument to the constructor of QGraphicsPG but that's no clean coding, in my view...
    Is there anything special about some Qt objects that prevents downcasting ?

    JonBJ 1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi
      Did you try
      http://doc.qt.io/qt-5/qobject.html#qobject_cast

      TGVFT 1 Reply Last reply
      1
      • mrjjM mrjj

        Hi
        Did you try
        http://doc.qt.io/qt-5/qobject.html#qobject_cast

        TGVFT Offline
        TGVFT Offline
        TGVF
        wrote on last edited by
        #3

        @mrjj
        Thanks for your suggestion!
        I added the Q_OBJECT macro in the GraphicsScenePG header and tried the cast:

        GraphicsScenePG *scene= qobject_cast<GraphicsScenePG*>(this->scene())  ;
        

        But obtained the same result as with dynamic_cast or static_cast (compiles but cast fails; access to nbMax crashes the execution).
        By the way, I figured out that the Q_OBJECT macro might be missing also in the QGraphicsPG header, so I added it there, but then the code won't compile anymore, saying:

        D:\Qt-apps\PG_Qt\qgraphicspg.cpp:-1: erreur : undefined reference to `vtable for QGraphicsPG'
        

        Waou

        1 Reply Last reply
        0
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @TGVF said in QGraphicsScene casting to derived class failed:

          QGraphicsItem

          As far as i recall. QGraphicsItem is not a QObject subclass?

          Its very odd with the cast. i see no reason it should not work.
          this->scene() does return something non NULL?

          1 Reply Last reply
          0
          • TGVFT TGVF

            My code is implementing subclasses of QGraphicsScene and QGraphicsItem in order to define some additional members.
            In my MainWindow , a QGraphicsPG object (subclass of QGraphicsItem) is constructed and added to the GraphicsScenePG object (subclass of QGraphicsScene).
            Then, a QGraphicsPG function compute() is called and need to access some members of GraphicsScenePG , but I was not able to cast the scene() pointer of type QGraphicsScene to the subclass pointer of type QGraphicsPG .
            I tried:

            • implicit or explicit cast: compilation error

            • static_cast and dynamic cast: both compile OK but fail during execution

            • reinterpret_cast: I did not try this quite dangerous operator...

            Here below my (simplified) code with the dynamic_cast attempt:

            // class GraphicsScenePG (header)
            #include <QGraphicsScene>
            class GraphicsScenePG : public QGraphicsScene
            {
            public:
                int nbMax ;
                GraphicsScenePG();
            }
            // class GraphicsScenePG (implementation)
            #include "GraphicsScenePG.h"
            GraphicsScenePG::GraphicsScenePG() : QGraphicsScene()  {    nbMax= 1 ;  }
            
            // class QGraphicsPG (header)
            #include <QGraphicsItem>
            class PG_Qt_MainWindow ;
            class QGraphicsPG : public QGraphicsItem
            {
            public:
                QGraphicsPG( QGraphicsItem *parent = 0 );
                ~QGraphicsPG();
                QRectF boundingRect() const ;
                void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                               QWidget *widget) ;
               void compute() ;
            }
            // class QGraphicsPG (implementation)
            #include <QtGui>
            #include "qgraphicspg.h"
            #include "pg_qt_mainwindow.h"
            QGraphicsPG::QGraphicsPG(QGraphicsItem *parent) : QGraphicsItem(parent)
            {
            //...
            }
            void QGraphicsPG::compute() {
                GraphicsScenePG *scene= (dynamic_cast<GraphicsScenePG*>(this->scene()) ) ; // cast failed!
                qDebug()<<"casted pointer="<<scene ;
            } 
            
            // class PG_Qt_MainWindow (header)
            #include <QMainWindow>
            #include "GraphicsScenePG.h"
            namespace Ui {  class PG_Qt_MainWindow; }
            class PG_Qt_MainWindow : public QMainWindow
            {
                Q_OBJECT
            public:
                explicit PG_Qt_MainWindow(QWidget *parent = 0);
                ~PG_Qt_MainWindow();
            private slots:
                 void PG_Qt_MainWindow::on_actionDummy_triggered();
            private:
                Ui::PG_Qt_MainWindow *ui;
                GraphicsScenePG scene ; 
            };
            // class PG_Qt_MainWindow (implementation)
            #include "pg_qt_mainwindow.h"
            #include "ui_pg_qt_mainwindow.h"
            #include <QtGui>
            
            PG_Qt_MainWindow::PG_Qt_MainWindow(QWidget *parent) :
                QMainWindow(parent), 
                ui(new Ui::PG_Qt_MainWindow) ,
                scene() 
            {
                ui->setupUi(this);
                ui->graphicsView->setScene(&scene);
                ui->graphicsView->show() ;
                qDebug()<<"nbMax="<<scene.nbMax ; // OK so far!
            }
               void PG_Qt_MainWindow::on_actionDummy_triggered();
            {
                        QGraphicsPG* item= new QGraphicsPG(0) ;
                        scene.addItem(item);
                       item.compute() ;
            }
            

            Execution gives:

            casted pointer= QObject(0x0)
            

            Trying to access the nbMax member from this incorrect pointer (null pointer?) crashes the execution.
            Of course, I could circumvent the issue e.g. passing the scene pointer of type GraphicsScenePG directly as an argument to the constructor of QGraphicsPG but that's no clean coding, in my view...
            Is there anything special about some Qt objects that prevents downcasting ?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @TGVF said in QGraphicsScene casting to derived class failed:

               void PG_Qt_MainWindow::on_actionDummy_triggered();
            {
                        QGraphicsPG* item= new QGraphicsPG(0) ;
                        scene.addItem(item);
                       item.compute() ;
            }
            

            I might be rushing in, because I'm not a C++-er, but item is a pointer to a QGraphicsPG, and yet you call item.compute() not item->compute()? How does that work? (It doesn't perchance do it like calling nullptr->compute(), where C++ allows you to call member functions on a null instance, giving them a null this, does it?) In compute() you should deffo print out this->scene() before you do your cast. EDIT: Also, if this-scene() is non-null, try dynamic_cast<QGraphicsScene*>(this->scene()) ?

            Or is all this code not the literal code used before you "simplified"?

            TGVFT 1 Reply Last reply
            1
            • JonBJ JonB

              @TGVF said in QGraphicsScene casting to derived class failed:

                 void PG_Qt_MainWindow::on_actionDummy_triggered();
              {
                          QGraphicsPG* item= new QGraphicsPG(0) ;
                          scene.addItem(item);
                         item.compute() ;
              }
              

              I might be rushing in, because I'm not a C++-er, but item is a pointer to a QGraphicsPG, and yet you call item.compute() not item->compute()? How does that work? (It doesn't perchance do it like calling nullptr->compute(), where C++ allows you to call member functions on a null instance, giving them a null this, does it?) In compute() you should deffo print out this->scene() before you do your cast. EDIT: Also, if this-scene() is non-null, try dynamic_cast<QGraphicsScene*>(this->scene()) ?

              Or is all this code not the literal code used before you "simplified"?

              TGVFT Offline
              TGVFT Offline
              TGVF
              wrote on last edited by
              #6

              @JonB
              In fact, this "simplified" code is not the literal one; actually , the operator -> is used, not "." . Otherwise, it would not compile.
              I now debug-print as follows:

                   qDebug()<<"original scene pointer="<<(int)(this->scene()) ;
                  qDebug()<<"dynamic_casted scene pointer="<<(int)(dynamic_cast<GraphicsScenePG*>(this->scene()) ) ;
                  qDebug()<<"qobject_casted scene pointer="<<(int)(qobject_cast<GraphicsScenePG*>(this->scene()) ) ;
                  qDebug()<<"original scene width()="<<(this->scene()->width()) ;
              
              

              which dumps the following lines:

              original scene pointer= 0
              dynamic_casted scene pointer= 0
              qobject_casted scene pointer= 0
              

              And then run crashes (of course!) since the scene()->width() can't be accessed.
              So the problem is not with the cast statement but with the scene() function returning NULL.
              Nonethless, this QGraphicsItem does paint correctly on the scene as it is visible in the window.
              May be because it was constructed with (default) parent=0 ? Documentation says constructing with parent=0 is possible if addItem(item) is used. Is this the reason why scene() returns NULL?

              JonBJ 1 Reply Last reply
              0
              • TGVFT TGVF

                @JonB
                In fact, this "simplified" code is not the literal one; actually , the operator -> is used, not "." . Otherwise, it would not compile.
                I now debug-print as follows:

                     qDebug()<<"original scene pointer="<<(int)(this->scene()) ;
                    qDebug()<<"dynamic_casted scene pointer="<<(int)(dynamic_cast<GraphicsScenePG*>(this->scene()) ) ;
                    qDebug()<<"qobject_casted scene pointer="<<(int)(qobject_cast<GraphicsScenePG*>(this->scene()) ) ;
                    qDebug()<<"original scene width()="<<(this->scene()->width()) ;
                
                

                which dumps the following lines:

                original scene pointer= 0
                dynamic_casted scene pointer= 0
                qobject_casted scene pointer= 0
                

                And then run crashes (of course!) since the scene()->width() can't be accessed.
                So the problem is not with the cast statement but with the scene() function returning NULL.
                Nonethless, this QGraphicsItem does paint correctly on the scene as it is visible in the window.
                May be because it was constructed with (default) parent=0 ? Documentation says constructing with parent=0 is possible if addItem(item) is used. Is this the reason why scene() returns NULL?

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @TGVF

                May be because it was constructed with (default) parent=0 ? Documentation says constructing with parent=0 is possible if addItem(item) is used. Is this the reason why scene() returns NULL?

                I don't think that will matter because your scene.addItem(item); will set its parent. But if you want to be sure, why don't you just pass scene to the constructor to test, and then you'll know?

                It can be difficult to tell when the code shown is not the actual code compiled...

                TGVFT 1 Reply Last reply
                2
                • JonBJ JonB

                  @TGVF

                  May be because it was constructed with (default) parent=0 ? Documentation says constructing with parent=0 is possible if addItem(item) is used. Is this the reason why scene() returns NULL?

                  I don't think that will matter because your scene.addItem(item); will set its parent. But if you want to be sure, why don't you just pass scene to the constructor to test, and then you'll know?

                  It can be difficult to tell when the code shown is not the actual code compiled...

                  TGVFT Offline
                  TGVFT Offline
                  TGVF
                  wrote on last edited by
                  #8

                  @JonB
                  Oups, I found my blunder! In the body of QGraphicsPG constructor (not shown on my simplified code), the compute() function is also called i.e. BEFORE this object is added to the scene, hence scene() is not yet allocated a value.
                  In the subsequent calls made by the slot on_actionDummy_triggered, everything is OK and dynamic_cast works perfectly.
                  Thanks JonB a lot for your help!

                  1 Reply Last reply
                  1

                  • Login

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