Problems initializing Qt and Qml inside a class..



  • I've been having a few issues organizing my Qt project. Specifically, moving a lot of the Qt initialization stuff out of my main.cpp and into a singleton class. By default, for a QtQuick2 application, QtCreator gives you a main.cpp file that looks something like this:

    @
    #include "QGuiApplication"
    #include "QQmlApplicationEngine"

    int main(int argc, char * argv[])
    {
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine();
    engine.load(QUrl( QStringLiteral("qrc:///MyQml.qml") );

    return app.exec();
    

    }
    @

    That was fine when I started building my app, but as my project grew I decided it might be better to have a C++ singleton class that's meant to encapsulate my whole program. That way I could add functionality to my program, load config files, and do other such things without jamming a bunch of sloppy-looking things into my main function. So, I made something that looked like this:

    --- MyProject.h ---
    @
    #ifndef MYPROJECT_H
    #define MYPROJECT_H

    #include "QObject.h"
    class QGuiApplication;
    class QQmlApplicationEngine;
    #define MYPROJECT MyProject::getInstance()

    class MyProject : public QObject
    {
    Q_OBJECT
    private:
    explicit MyProject(QObject *parent = 0); //singleton..
    MyProject(MyProject const&); //uncopyable..
    void operator=(MyProject const&); //unassignable..
    QGuiApplication * QtGUI;
    QQmlApplicationEngine * QmlAppEngine;

    public:
    ~MyProject(void);

    /* Globally available function to get MyProject's singleton instance.
     * You can use the "MYPROJECT" preprocessor macro for shorthand. */
    static MyProject & getInstance(void)
    {
        static MyProject instance;
        return instance;
    }
    
    int init(int argc, char * argv[]);
    int exec(void);
    

    signals:
    public slots:
    };

    #endif
    @

    --- MyProject.cpp (minus the fat..) ---
    @
    //ctor initialization list inits pointers to NULL etc..
    //dtor frees pointers if not null..
    //etc.. etc...

    int MyProject::init(int argc, char * argv[])
    {
    QtGUI = new QGuiApplication(argc, argv);
    QmlAppEngine = new QQmlApplicationEngine();

    if(QtGUI && QmlAppEngine)
    {
        //register a bunch of custom QML types etc..
        return 0;
    }
    else return 1;
    

    }

    int MyProject::exec(void)
    {
    QmlAppEngine->load(QUrl( QStringLiteral("qrc:///MyQml.qml") ));
    return QtGUI->exec();
    }
    @

    --- new version of main.cpp ---
    @
    #include "MyProject.h"

    int main(int argc, char * argv[])
    {
    MYPROJECT.init(argc, argv);
    return MYPROJECT.exec();
    }
    @

    Now my program is compiling fine, and seems to be functioning correctly aside from a few new issues:

    (1) Qt.quit() no longer works correctly. One of my QML object's onClicked event handlers calls Qt.Quit(), and while it worked perfectly before, my program no longer quits properly when the item is clicked. I get a message "The program has unexpectedly finished." along with a crash. I'm not sure why this is happening, but I suspect its somehow related to my QGuiApplication and QQmlApplicationEngine being pointers instead of objects.. How would I go about fixing this?

    (2) "QmlAppEngine->load(QUrl( QStringLiteral("qrc:///MyQml.qml") ));" Only works correctly inside the MyProject::exec() method. I tried placing it in my MyProject::init(int, char*) method after the allocation of my QGuiApplication and QQmlApplicationEngine objects, but it seems like it threw an exception or something because it seemed to cause the init function to back out without running completely. Is there some reason why this would be throwing an exception in the init() method but not the exec() method?

    So, I'm not sure if this has really been worth it at all so far. I wasn't expecting things to work differently just by changing the location of a few objects. Now I'm wondering if there is a better way of initializing Qt within a singleton object instead of in my program's main function. Does any one else bother with this? Is it just more trouble than its worth? Is there some obvious way that I can fix or improve this system to get it working more correctly?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.