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. [SOLVED] QWidget: Must construct a QApplication before a QWidget
QtWS25 Last Chance

[SOLVED] QWidget: Must construct a QApplication before a QWidget

Scheduled Pinned Locked Moved General and Desktop
21 Posts 4 Posters 47.9k 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.
  • J Offline
    J Offline
    Jojo1704
    wrote on last edited by
    #1

    Hello,

    I am working on a project with Qt 5.2.1. and VTK 6.1.

    For the visualization I am trying to implement a MeshWrapper class that spawns multiple QVTKWidgets as Mdi windows.
    When I try to instantiate a new mdi child from my MeshWrapper class I get the error:
    @QWidget: Must construct a QApplication before a QWidget@

    Afterwards the program execution stops.

    When instantiating it directly from the mainwindow it works fine!

    I read that this error can occur, when the Widget gets declared somewhere in the header before the QApplication is created, but the mdi child is only created in a function of the MeshWrapper which is called from the mainwindow.

    Can anyone help me resolve this error?

    Thank You

    @class MeshWrapper : public QObject
    {
    Q_OBJECT
    public:
    MeshWrapper();

    bool loadFile(const QString &fileName);
    bool createMeshes(QMdiArea *mdiArea);
    

    signals:

    public slots:

    private:
    vtkSmartPointer<vtkPolyData> polyData[2];
    };@

    @bool MeshWrapper::createMeshes(QMdiArea *mdiArea) {
    mdiVTKChild *mesh1 = new mdiVTKChild();
    mesh1->render();

    mdiArea->addSubWindow(mesh1);
    mesh1->show();
    
    return true;
    

    }@

    @class mdiVTKChild : public QVTKWidget
    {
    Q_OBJECT
    public:
    mdiVTKChild();
    mdiVTKChild(vtkSmartPointer<vtkPolyData> _polyData);

    bool loadFile&#40;const QString &fileName&#41;;
    bool render(&#41;;
    

    signals:

    public slots:

    private:
    vtkSmartPointer<vtkPolyData> polyData;
    };@

    @void MainWindow::on_actionRead_Liver_triggered()
    {
    QString filename = QFileDialog::getOpenFileName(this,tr("Open File"), "C:/", tr("(*.txt)"));

    MeshWrapper *meshWrapper = new MeshWrapper();
    meshWrapper->loadFile&#40;filename&#41;;
    meshWrapper->createMeshes(ui->mdiArea&#41;;
    

    }
    @

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      Can you post the main function here, too?

      (Z(:^

      1 Reply Last reply
      0
      • J Offline
        J Offline
        Jojo1704
        wrote on last edited by
        #3

        Thank you for your reply. This is the main function:

        @#include "mainwindow.h"
        #include <QApplication>

        int main(int argc, char *argv[])
        {
        QApplication a(argc, argv);
        MainWindow w;
        w.showMaximized();

        return a.exec&#40;&#41;;
        

        }@

        1 Reply Last reply
        0
        • sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          Hm, that looks good.

          ... apart from the fact that you indeed are including QApplication header after mainwindow.h, which is precisely what you warned agains in your initial post ;P

          Still, it should work, IMO.

          (Z(:^

          1 Reply Last reply
          0
          • J Offline
            J Offline
            Jojo1704
            wrote on last edited by
            #5

            I just switched the 2 includes, no difference. The main function was generated by QtCreator.
            Also it works when I create the mdi child directly in the mainwindow, which confuses me.

            Is it possible that it happens, because the MeshWrapper base is QObject and not QWidget?

            1 Reply Last reply
            0
            • M Offline
              M Offline
              mlong
              wrote on last edited by
              #6

              Just for fun, you might set a breakpoint at the instantiation of your QApplication and in the ctor of your MeshWrapper class, just to see for yourself which is being instantiated first.

              Software Engineer
              My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

              1 Reply Last reply
              0
              • sierdzioS Offline
                sierdzioS Offline
                sierdzio
                Moderators
                wrote on last edited by
                #7

                Ah, I have missed that part. In theory, it should not be a problem, although it might indicate that a better idea would be to clearly separate the logic from the UI (might help a lot down the line): so, move the widget creation to your GUI classes.

                Remove the brackets from this line, too:
                @
                // old
                mdiVTKChild *mesh1 = new mdiVTKChild();

                // new
                mdiVTKChild *mesh1 = new mdiVTKChild;
                @

                Also, please be careful with your mesh1->render() function: you are instantiating the mdiVTKChild without a parent, so it will be created as a separate window. Maybe modify your code and pass the QMdiArea as parent for mdiVTKChild?

                (Z(:^

                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  Jojo1704
                  wrote on last edited by
                  #8

                  Thank you for your replies.

                  bq. Just for fun, you might set a breakpoint at the instantiation of your QApplication and in the ctor of your MeshWrapper class, just to see for yourself which is being instantiated first.

                  I did that. QApplication is being instantiated before any GUI is shown and MeshWrapper much later.

                  I also did what sierdzio said, but no success either.

                  This error keeps me busy for two days now... Any more ideas?

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andreyc
                    wrote on last edited by
                    #9

                    If you are getting this error exactly on
                    @
                    mdiVTKChild *mesh1 = new mdiVTKChild();
                    @

                    Add a debug output for qApp before creating mdiVTKChild.
                    You may need to include QApplication to get qApp.
                    @
                    #include <QApplication>
                    ...
                    qDebug() << qApp;
                    mdiVTKChild *mesh1 = new mdiVTKChild();
                    ...
                    @

                    1 Reply Last reply
                    0
                    • J Offline
                      J Offline
                      Jojo1704
                      wrote on last edited by
                      #10

                      Yes, it happens exactly on this line, but only if it is called from the MeshWrapper class.

                      I did what you said, this is the output:

                      @
                      QApplication(0xa99640fae0)
                      QWidget: Must construct a QApplication before a QWidget
                      @

                      Looks like qApp exists, doesn't it?

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        andreyc
                        wrote on last edited by
                        #11

                        "It's not possible" (c) Boris the animal from MIB3
                        @
                        QApplication(0xa99640fae0)
                        QWidget: Must construct a QApplication before a QWidget
                        @

                        Apparently we are loosing qApp between this new operator and QWidget() constructor.

                        Could you put here a source for mdiVTKChild constructor.

                        Could you step in inside mdiVTKChild() constructor and then inside QWidget() in debugger.

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          Jojo1704
                          wrote on last edited by
                          #12

                          These are two constructors:

                          @mdiVTKChild::mdiVTKChild(QWidget *parent, vtkSmartPointer<vtkPolyData> _polyData) :
                          QVTKWidget(parent)
                          {
                          polyData = _polyData;
                          }

                          mdiVTKChild::mdiVTKChild(vtkSmartPointer<vtkPolyData> _polyData)
                          {
                          setAttribute(Qt::WA_DeleteOnClose);
                          this->setMinimumSize(QSize(300, 300));

                          polyData = _polyData;
                          

                          }

                          @

                          The error appears for both of them. The program stops, before the debugger breaks on them.

                          If I step in from the instantiation of the child, I get to the header of the constructor and stops there.

                          What could that mean?

                          1 Reply Last reply
                          0
                          • A Offline
                            A Offline
                            andreyc
                            wrote on last edited by
                            #13

                            In you header file you have declared two constructors.
                            One default and one with _polyData as a parameter.
                            @
                            public:
                            mdiVTKChild();
                            mdiVTKChild(vtkSmartPointer<vtkPolyData> _polyData);
                            @

                            In your source code you don't have default constructor but there is another non-default constructor.
                            @
                            mdiVTKChild::mdiVTKChild(QWidget *parent, vtkSmartPointer<vtkPolyData> _polyData) : QVTKWidget(parent)
                            {
                            polyData = _polyData;
                            }

                            mdiVTKChild::mdiVTKChild(vtkSmartPointer<vtkPolyData> _polyData)
                            {
                            ...
                            }
                            @

                            When you creating new mdiVTKChild object you are calling a default constructor, which is declared but not defined.
                            @
                            bool MeshWrapper::createMeshes(QMdiArea *mdiArea)
                            {
                            mdiVTKChild *mesh1 = new mdiVTKChild();
                            ...
                            }
                            @

                            Is it possible that you are mixing some old and new code and getting a memory corruption because of that?

                            1 Reply Last reply
                            0
                            • J Offline
                              J Offline
                              Jojo1704
                              wrote on last edited by
                              #14

                              Actually I changed both, the header and the implementation. I just forgot to post the new header:

                              @public:
                              mdiVTKChild(QWidget *parent, vtkSmartPointer<vtkPolyData> _polyData);
                              mdiVTKChild(vtkSmartPointer<vtkPolyData> _polyData);
                              @

                              Sorry for the confusion. But I would be happy if that was the problem :D

                              1 Reply Last reply
                              0
                              • A Offline
                                A Offline
                                andreyc
                                wrote on last edited by
                                #15

                                And you are sure that VTKWidget does not try to create any global QWidgets.
                                And there no other threads that were started by some global variables and try to create mdiVTKChild before QApplication is created.

                                If so then I think you need to go (debug) deeper.

                                But before that. Try to create a small (as small as possible) application that just creates mdiVTKChild.
                                Does it produce the same error?

                                Now to the debugger.
                                Run your app with gdb in command line not in qtcreator.
                                This "link":http://stackoverflow.com/questions/58851/can-i-set-a-breakpoint-on-memory-access-in-gdb/59146#59146 explains how to set a breakpoint on a memory access.

                                Modify main()
                                @
                                ...
                                QApplication a(argc, argv);
                                qDebug() << "qApp =" << qApp << "address of qApp =" << &qApp;
                                ...
                                @

                                • Add a breakpoint on main() step through qDebug() and see what address do you have.
                                • Put memory access breakpoint on that address and run you app.
                                • See if qApp will be changed before you will get that "must construct" error.
                                1 Reply Last reply
                                0
                                • J Offline
                                  J Offline
                                  Jojo1704
                                  wrote on last edited by
                                  #16

                                  I will try the deeper debugging. But to answer your question:

                                  It only gives me the error when I create mdiVTKChild inside the MeshWrapper class.
                                  When I call "new mdiVTKChild" from my mainwindow.cpp in the function it works.

                                  Works:

                                  @void MainWindow::on_actionRead_Liver_triggered()
                                  {
                                  QString filename = QFileDialog::getOpenFileName(this,tr("Open File"), "C:/", tr("(*.txt)"));

                                  mdiVTKChild *mesh1 = new mdiVTKChild();
                                  mesh1->loadFile&#40;filename&#41;;
                                  mesh1->render();
                                  
                                  ui->mdiArea->addSubWindow(mesh1);
                                  mesh1->show();
                                  

                                  }@

                                  Doesnot work:

                                  @void MainWindow::on_actionRead_Liver_triggered()
                                  {
                                  QString filename = QFileDialog::getOpenFileName(this,tr("Open File"), "C:/", tr("(*.txt)"));

                                  MeshWrapper *meshWrapper = new MeshWrapper();
                                  meshWrapper->loadFile&#40;filename&#41;;
                                  meshWrapper->createMeshes(ui->mdiArea);
                                  

                                  }
                                  @

                                  1 Reply Last reply
                                  0
                                  • A Offline
                                    A Offline
                                    andreyc
                                    wrote on last edited by
                                    #17

                                    Have you tried to pass ui->mdiArea to mdiVTKChild() as a parent widget?

                                    1 Reply Last reply
                                    0
                                    • J Offline
                                      J Offline
                                      Jojo1704
                                      wrote on last edited by
                                      #18

                                      Yes, but that makes no difference.

                                      But I think I was able to narrow it down:

                                      I was wondering if it could have something to do with the fact, that the child is a QVTKWidget and not a QWidget, so I changed the base of the class and threw out all the VTK stuff. Apparently that works.

                                      So it has something to do with the QVTKWidget. But why does QVTKWidget work, when created in the mainwindow?

                                      I will try to debug the QVTKWidget, perhaps it's just something I missed to pass to the MeshWrapper from the mainwindow...

                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        andreyc
                                        wrote on last edited by
                                        #19

                                        bq. But why does QVTKWidget work, when created in the mainwindow?

                                        Is it possible that in case of error you are trying to create QVTKWidget not in main GUI thread?

                                        1 Reply Last reply
                                        0
                                        • J Offline
                                          J Offline
                                          Jojo1704
                                          wrote on last edited by
                                          #20

                                          I finally made it. After pinning it on the QVTKWidget I was sure it was VTKs fault and not my code.
                                          I guessed it is much more likely, that I made an error building and linking VTK on my machine than an error in VTK.
                                          So I reworked everything and included the information I found here:
                                          http://public.kitware.com/pipermail/vtkusers/2011-August/069256.html

                                          After some playing around it finally worked.

                                          Sorry for bugging you with Qt questions, when in the end it was a matter of combining Qt and VTK, but thank you so much for your ongoing participation and effort in finding my error :)

                                          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