Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. qmlRegisterType still usable?
Forum Updated to NodeBB v4.3 + New Features

qmlRegisterType still usable?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
7 Posts 5 Posters 1.6k Views 3 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.
  • R Offline
    R Offline
    RangerQT
    wrote on 12 Feb 2024, 03:08 last edited by
    #1

    Some time ago I started using Qt6 but had to stop and am now picking it pack up with 6.6.1. I have a QML project that has a C++ class that I want to invoke from QML. For testing purposes it just does a qDebug() output and is declared with the Q_INVOKABLE macro. The class exists in a subdirectory of the project so I have

    Project - CMakeLists.txt, Main.qml, main.cpp
    utilities - CMakeLists.txt, utilities.h, utilities.cpp

    The project CMakelists.txt has add_subdirectory(utilities) and this to link the result.
    target_link_libraries(appAirmailBeacons
    PRIVATE utilities_moduleplugin
    )

    In past projects I used qmlRegisterType<T>("name", major, minor, Somename) in main.cpp and this worked. However, reading through Qt Blogs (https://www.qt.io/blog/qml-modules-in-qt-6.2, https://www.qt.io/blog/whats-new-for-qml-modules-in-6.5 and others) and looking at the Qt 6.6 docs I am confused totally!

    From what I can get from the Blogs I simply have to define a static library in my subdirectory CMakeLists.txt, use the qt6_add_qml_module(name URI utilities Version 1.0 SOURCES utilities.h utilities.cpp) and then link this library in the main project CMakeLists.txt.

    I then should be able to use the Q_IMPORT_QML_PLUGIN(utilitiesPlugin,), import utilities in the QML file and it should work and can can use call the function as utilitities.test(). This doesn't work. I get a test is not defined error.

    From past experience I know engine.rootContext()->setContextProperty(blah) can be used as well as qmlRegisterType but based on my reading those seem to be discouraged. The Qt 6.6 examples keep referring to QQuickview and view.set but I'm using QQmlApplicationEngine which was set when I created the project and I understand QQmlApplication Engine replaces QQuickview.

    So for Qt6 what is the official method way to have items from C++. I really would like to use the "correct Qt6" way but from my research and reading what I thought I should do does not work. The application builds correctly but tells me when I call utilities.test() that test is undefined.

    1. If I simply want to call a C++ function that is QINVOKABLE from QML what do I need. Do I use the Q_IMPORT_QML_PLUGIN and if so how to make it work, and/or engine.rootContext(), and/or qmlRegisterType? From what I can find I should register it.

    2. If I want to create an instance of it for use in QML as in mystuff {blah} in a QML file I should use the rootContext from what I can find out.

    However, the Blogs seem to indicate I do not need this.

    Thank you. Any insight is appreciated.

    Code:
    Project CMakeLists.txt

    #=============================================================================
    # Project setup
    cmake_minimum_required(VERSION 3.16)
    project(AirmailBeacons VERSION 0.1 LANGUAGES CXX)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    #=============================================================================
    # Various constants.
    # Set application name for use in building.
    set(appName "AirmailBeacons")
    #=============================================================================
    
    find_package(Qt6 REQUIRED COMPONENTS
        Core
        Qml
        Quick
    )
    
    qt_standard_project_setup(REQUIRES 6.5)
    
    #=============================================================================
    # The executable
    qt_add_executable(appAirmailBeacons
        main.cpp
    )
    
    #==============================================================================
    # Our subdirectories
    add_subdirectory (
        utilities
    )
    
    #=============================================================================
    #QML modules
    qt_add_qml_module(appAirmailBeacons
        URI AirmailBeacons
        VERSION 1.0
        QML_FILES
            Main.qml
    )
    
    #=============================================================================
    # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
    # If you are developing for iOS or macOS you should consider setting an
    # explicit, fixed bundle identifier manually though.
    set_target_properties(appAirmailBeacons PROPERTIES
    #    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appAirmailBeacons
        MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
        MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
        MACOSX_BUNDLE TRUE
        WIN32_EXECUTABLE TRUE
    )
    
    #==============================================================================
    # Libraries
    target_link_libraries(appAirmailBeacons
        PRIVATE Qt6::Core
        PRIVATE Qt6::Quick
        PRIVATE Qt6::Qml
    )
    
    #==============================================================================
    # Our libraries
    target_link_libraries(appAirmailBeacons
        PRIVATE utilities_moduleplugin
    )
    
    #=============================================================================
    include(GNUInstallDirs)
    install(TARGETS appAirmailBeacons
        BUNDLE DESTINATION .
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    )
    
    #=============================================================================
    # Set target properties
    set_target_properties(appAirmailBeacons PROPERTIES OUTPUT_NAME ${appName})
    #=============================================================================
    # Copy the file after it's built.
    
    

    utilities/CMakeList.txt

    # CMakeLists.txt to build import backend.
    
    qt_add_library(utilities_module STATIC)
    qt6_add_qml_module(utilities_module
        URI utilities
        VERSION 1.0
        SOURCES
            utilities.h
            utilities.cpp
    )
    
    

    main.cpp

    // Qt includes
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QtQml/QQmlExtensionPlugin>
    
    // Our includes
    #include "utilities/utilities.h"
    
    // Our Imports
    Q_IMPORT_QML_PLUGIN(utilitiesPlugin)
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        QObject::connect(
            &engine,
            &QQmlApplicationEngine::objectCreationFailed,
            &app,
            []() { QCoreApplication::exit(-1); },
            Qt::QueuedConnection);
        engine.loadFromModule("AirmailBeacons", "Main");
    
        return app.exec();
    }
    
    

    Main.qml

    // QML imports
    import QtQuick
    import QtQuick.Controls
    import QtQml
    
    // Our imports
    import utilities 1.0
    
    ApplicationWindow {
        width: 640
        height: 480
        visible: true
        title: qsTr("Airmail Beacons")
    
        // Menu Bar
        menuBar: MenuBar {
            Menu {
                id: fileMenu
                title: qsTr("&File")
                MenuItem {
                    text: "&Open"
                    onTriggered: {
                        console.log("Open")
                        //utilities:test()
                    }
                }
                MenuSeparator {}
                MenuItem {
                    text: qsTr("&Quit")
                    onTriggered: {
                        Qt.exit(0)
                    }
                }
            } // End File Menu
        } //  End Menubar
    } // End ApplicationWindow
    

    utilities.h

    #ifndef UTILITIES_H
    #define UTILITIES_H
    
    // Qt includes
    #include <QObject>
    #include <QQmlEngine>
    #include <QString>
    #include <QtQml/qqmlregistration.h>
    #include <QUrl>
    #include <QDir>
    
    //Our includes
    #include <QDebug>
    
    class Utilities : public QObject
    {
        Q_OBJECT
        QML_ELEMENT
    
    public:
        explicit Utilities(QObject *parent = nullptr);
    
        //=========================================================================
        // Functions
        QString urltonativepath(const QUrl& urlpath);
    
        //-----------------------------------------------------------------------------
        // Test function
        Q_INVOKABLE void test();
    
    
        //=========================================================================
        // Signals
    signals:
    
    }; // End class Utilities.
    
    #endif // UTILITIES_H
    
    

    utilities.cpp

    #include "utilities.h"
    
    Utilities::Utilities(QObject *parent)
        : QObject{parent}
    {
    
    }
    
    //=============================================================================
    // Functions
    // QString urltonativepath(const Qurl &urlpath) - converts url to native
    // file path.
    //
    // Parameters:
    //  urlpath - the url to convert
    //
    // Returns:
    //  native file path as a Qstring.
    
    QString Utilities::urltonativepath(const QUrl &urlpath)
    {
        return QDir::toNativeSeparators(urlpath.toLocalFile());
    
    }
    
    //-----------------------------------------------------------------------------
    // Test
    void Utilities::test()
    {
        qInfo() << "Called test";
    } // End urltonativepath
    
    
    R 1 Reply Last reply 12 Feb 2024, 20:51
    1
    • R RangerQT
      12 Feb 2024, 03:08

      Some time ago I started using Qt6 but had to stop and am now picking it pack up with 6.6.1. I have a QML project that has a C++ class that I want to invoke from QML. For testing purposes it just does a qDebug() output and is declared with the Q_INVOKABLE macro. The class exists in a subdirectory of the project so I have

      Project - CMakeLists.txt, Main.qml, main.cpp
      utilities - CMakeLists.txt, utilities.h, utilities.cpp

      The project CMakelists.txt has add_subdirectory(utilities) and this to link the result.
      target_link_libraries(appAirmailBeacons
      PRIVATE utilities_moduleplugin
      )

      In past projects I used qmlRegisterType<T>("name", major, minor, Somename) in main.cpp and this worked. However, reading through Qt Blogs (https://www.qt.io/blog/qml-modules-in-qt-6.2, https://www.qt.io/blog/whats-new-for-qml-modules-in-6.5 and others) and looking at the Qt 6.6 docs I am confused totally!

      From what I can get from the Blogs I simply have to define a static library in my subdirectory CMakeLists.txt, use the qt6_add_qml_module(name URI utilities Version 1.0 SOURCES utilities.h utilities.cpp) and then link this library in the main project CMakeLists.txt.

      I then should be able to use the Q_IMPORT_QML_PLUGIN(utilitiesPlugin,), import utilities in the QML file and it should work and can can use call the function as utilitities.test(). This doesn't work. I get a test is not defined error.

      From past experience I know engine.rootContext()->setContextProperty(blah) can be used as well as qmlRegisterType but based on my reading those seem to be discouraged. The Qt 6.6 examples keep referring to QQuickview and view.set but I'm using QQmlApplicationEngine which was set when I created the project and I understand QQmlApplication Engine replaces QQuickview.

      So for Qt6 what is the official method way to have items from C++. I really would like to use the "correct Qt6" way but from my research and reading what I thought I should do does not work. The application builds correctly but tells me when I call utilities.test() that test is undefined.

      1. If I simply want to call a C++ function that is QINVOKABLE from QML what do I need. Do I use the Q_IMPORT_QML_PLUGIN and if so how to make it work, and/or engine.rootContext(), and/or qmlRegisterType? From what I can find I should register it.

      2. If I want to create an instance of it for use in QML as in mystuff {blah} in a QML file I should use the rootContext from what I can find out.

      However, the Blogs seem to indicate I do not need this.

      Thank you. Any insight is appreciated.

      Code:
      Project CMakeLists.txt

      #=============================================================================
      # Project setup
      cmake_minimum_required(VERSION 3.16)
      project(AirmailBeacons VERSION 0.1 LANGUAGES CXX)
      set(CMAKE_CXX_STANDARD_REQUIRED ON)
      
      #=============================================================================
      # Various constants.
      # Set application name for use in building.
      set(appName "AirmailBeacons")
      #=============================================================================
      
      find_package(Qt6 REQUIRED COMPONENTS
          Core
          Qml
          Quick
      )
      
      qt_standard_project_setup(REQUIRES 6.5)
      
      #=============================================================================
      # The executable
      qt_add_executable(appAirmailBeacons
          main.cpp
      )
      
      #==============================================================================
      # Our subdirectories
      add_subdirectory (
          utilities
      )
      
      #=============================================================================
      #QML modules
      qt_add_qml_module(appAirmailBeacons
          URI AirmailBeacons
          VERSION 1.0
          QML_FILES
              Main.qml
      )
      
      #=============================================================================
      # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
      # If you are developing for iOS or macOS you should consider setting an
      # explicit, fixed bundle identifier manually though.
      set_target_properties(appAirmailBeacons PROPERTIES
      #    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appAirmailBeacons
          MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
          MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
          MACOSX_BUNDLE TRUE
          WIN32_EXECUTABLE TRUE
      )
      
      #==============================================================================
      # Libraries
      target_link_libraries(appAirmailBeacons
          PRIVATE Qt6::Core
          PRIVATE Qt6::Quick
          PRIVATE Qt6::Qml
      )
      
      #==============================================================================
      # Our libraries
      target_link_libraries(appAirmailBeacons
          PRIVATE utilities_moduleplugin
      )
      
      #=============================================================================
      include(GNUInstallDirs)
      install(TARGETS appAirmailBeacons
          BUNDLE DESTINATION .
          LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
          RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
      )
      
      #=============================================================================
      # Set target properties
      set_target_properties(appAirmailBeacons PROPERTIES OUTPUT_NAME ${appName})
      #=============================================================================
      # Copy the file after it's built.
      
      

      utilities/CMakeList.txt

      # CMakeLists.txt to build import backend.
      
      qt_add_library(utilities_module STATIC)
      qt6_add_qml_module(utilities_module
          URI utilities
          VERSION 1.0
          SOURCES
              utilities.h
              utilities.cpp
      )
      
      

      main.cpp

      // Qt includes
      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      #include <QtQml/QQmlExtensionPlugin>
      
      // Our includes
      #include "utilities/utilities.h"
      
      // Our Imports
      Q_IMPORT_QML_PLUGIN(utilitiesPlugin)
      
      int main(int argc, char *argv[])
      {
          QGuiApplication app(argc, argv);
      
          QQmlApplicationEngine engine;
          QObject::connect(
              &engine,
              &QQmlApplicationEngine::objectCreationFailed,
              &app,
              []() { QCoreApplication::exit(-1); },
              Qt::QueuedConnection);
          engine.loadFromModule("AirmailBeacons", "Main");
      
          return app.exec();
      }
      
      

      Main.qml

      // QML imports
      import QtQuick
      import QtQuick.Controls
      import QtQml
      
      // Our imports
      import utilities 1.0
      
      ApplicationWindow {
          width: 640
          height: 480
          visible: true
          title: qsTr("Airmail Beacons")
      
          // Menu Bar
          menuBar: MenuBar {
              Menu {
                  id: fileMenu
                  title: qsTr("&File")
                  MenuItem {
                      text: "&Open"
                      onTriggered: {
                          console.log("Open")
                          //utilities:test()
                      }
                  }
                  MenuSeparator {}
                  MenuItem {
                      text: qsTr("&Quit")
                      onTriggered: {
                          Qt.exit(0)
                      }
                  }
              } // End File Menu
          } //  End Menubar
      } // End ApplicationWindow
      

      utilities.h

      #ifndef UTILITIES_H
      #define UTILITIES_H
      
      // Qt includes
      #include <QObject>
      #include <QQmlEngine>
      #include <QString>
      #include <QtQml/qqmlregistration.h>
      #include <QUrl>
      #include <QDir>
      
      //Our includes
      #include <QDebug>
      
      class Utilities : public QObject
      {
          Q_OBJECT
          QML_ELEMENT
      
      public:
          explicit Utilities(QObject *parent = nullptr);
      
          //=========================================================================
          // Functions
          QString urltonativepath(const QUrl& urlpath);
      
          //-----------------------------------------------------------------------------
          // Test function
          Q_INVOKABLE void test();
      
      
          //=========================================================================
          // Signals
      signals:
      
      }; // End class Utilities.
      
      #endif // UTILITIES_H
      
      

      utilities.cpp

      #include "utilities.h"
      
      Utilities::Utilities(QObject *parent)
          : QObject{parent}
      {
      
      }
      
      //=============================================================================
      // Functions
      // QString urltonativepath(const Qurl &urlpath) - converts url to native
      // file path.
      //
      // Parameters:
      //  urlpath - the url to convert
      //
      // Returns:
      //  native file path as a Qstring.
      
      QString Utilities::urltonativepath(const QUrl &urlpath)
      {
          return QDir::toNativeSeparators(urlpath.toLocalFile());
      
      }
      
      //-----------------------------------------------------------------------------
      // Test
      void Utilities::test()
      {
          qInfo() << "Called test";
      } // End urltonativepath
      
      
      R Offline
      R Offline
      RangerQT
      wrote on 12 Feb 2024, 20:51 last edited by
      #2

      I found this topic extremely helpful and got a test case to work. However, I'm still working on getting the case where I have C++ classes in subdirectories working.

      https://forum.qt.io/topic/145977/registering-an-instantiable-object-type-official-example/5

      1 Reply Last reply
      0
      • L Offline
        L Offline
        LS-KS
        wrote on 12 Feb 2024, 20:57 last edited by
        #3

        This!!!!

        Last year I created a larger project using python and qml.
        I got confident and built tools with GUIs in widgets and C++. My actual learning project cannot be created from Qt Creator but from QT Design Studio.

        And since 6 days iI tried to get into how to connect my backend classes with my GUI (I want to load data from files, do data processing, handle user input, reprocess, create and display an svg from data).

        I said to myself: " don't waste others people time, read the reference". But the reference is somehow "to easy".
        Since I'm not a cmake-Jedi-master i mostly get stuck there. the blogs always look so different it almost feels like doing a microchip project: reference against unexperienced developer.

        back to topic:
        I created an object of my backend on heap. Then i tried to map the object to a QVariantMap and call setInitialProperties from QQmlApplicationEngine. But somehow i cannot do that because I'm failing to map the object (no matching constructor of the map).

        I hope someone can deliver a general solution.

        R 1 Reply Last reply 13 Feb 2024, 00:29
        0
        • L LS-KS
          12 Feb 2024, 20:57

          This!!!!

          Last year I created a larger project using python and qml.
          I got confident and built tools with GUIs in widgets and C++. My actual learning project cannot be created from Qt Creator but from QT Design Studio.

          And since 6 days iI tried to get into how to connect my backend classes with my GUI (I want to load data from files, do data processing, handle user input, reprocess, create and display an svg from data).

          I said to myself: " don't waste others people time, read the reference". But the reference is somehow "to easy".
          Since I'm not a cmake-Jedi-master i mostly get stuck there. the blogs always look so different it almost feels like doing a microchip project: reference against unexperienced developer.

          back to topic:
          I created an object of my backend on heap. Then i tried to map the object to a QVariantMap and call setInitialProperties from QQmlApplicationEngine. But somehow i cannot do that because I'm failing to map the object (no matching constructor of the map).

          I hope someone can deliver a general solution.

          R Offline
          R Offline
          RangerQT
          wrote on 13 Feb 2024, 00:29 last edited by
          #4

          @LS-KS Yes. Unfortunately, too many examples use complex situations and the learning message is lost in them as you try to separate the learning part from the application.

          1 Reply Last reply
          1
          • G Offline
            G Offline
            Groundbounce
            wrote on 20 Apr 2025, 15:37 last edited by
            #5

            So what is the answer? I totally lost the plot with the QT academy tutorial, others do the same. I want to do one thing, why tell me about other stuff?

            How do you connect C++ and QML? I have come to the conclusion that the QT company want to ditch C++ going forward as this one essential topic is never discussed in any meaningful way. Any information on QML says that it will not talk about C++, well Stroustrop will not exactly be telling you how to do it either as this is a QML thing not a C++ one. QT decided to go down the javascript/custom new language path, well now tell us how to use it in the context of reality. Reality is that we write our backends in C++!!

            jsulmJ 1 Reply Last reply 22 Apr 2025, 12:02
            0
            • JoeCFDJ Offline
              JoeCFDJ Offline
              JoeCFD
              wrote on 22 Apr 2025, 11:50 last edited by JoeCFD
              #6

              I do not know if QT company wants to ditch C++. I guess it may be unlikely.
              QML simply follows the trend just like
              Swift in iOS
              Flutter in Google
              It allows developers to define UI elements and their properties in a descriptive manner, rather than through imperative code. It may be relatively easier to make UI design.

              Ideally, it is better to set-up one standard which can be applied for any programming language. Coders do not need to spend time to learn all of them, Swift, Flutter and QML, ....

              1 Reply Last reply
              1
              • G Groundbounce
                20 Apr 2025, 15:37

                So what is the answer? I totally lost the plot with the QT academy tutorial, others do the same. I want to do one thing, why tell me about other stuff?

                How do you connect C++ and QML? I have come to the conclusion that the QT company want to ditch C++ going forward as this one essential topic is never discussed in any meaningful way. Any information on QML says that it will not talk about C++, well Stroustrop will not exactly be telling you how to do it either as this is a QML thing not a C++ one. QT decided to go down the javascript/custom new language path, well now tell us how to use it in the context of reality. Reality is that we write our backends in C++!!

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on 22 Apr 2025, 12:02 last edited by
                #7

                @Groundbounce said in qmlRegisterType still usable?:

                How do you connect C++ and QML?

                Like explained in the documentation: https://doc.qt.io/qt-6/qtqml-cppintegration-overview.html
                QtCompany will for sure not ditch C++ as QML is only for UI and some logic in the UI. Everything else is still C++.

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                2

                • Login

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