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. Register custom qml component using plugins

Register custom qml component using plugins

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 2 Posters 527 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.
  • M Offline
    M Offline
    Mighty_Pig
    wrote on 2 Apr 2024, 08:15 last edited by
    #1

    I recently started learning QT6 for a project I am working on.
    I am trying to create a GUI that contains some buttons and eventually text boxes too. In order to create the buttons, I created my custom qml component.
    The code for this button is as following:

    import QtQuick 6.6
    import QtQuick.Controls
    import QtQuick.Controls.Material
    import MyCustomButton
    
    Item {
        width: 300; height: 200
        objectName: "root item"
    
        MyCustomButton {
            id: button
            Material.background: Material.Red
            width: 50
            height: 50
            name: "test"
            objectName: "MyCustomButton"
        }
    
        Text {
                    id: name
                    text: button.name // Bind to the parent's text property
                    color: "black"
                    anchors.centerIn: button // Center text within the button
                    objectName: "MyCustomButtonText"
                }
        MouseArea {
                    id: mouseArea
                    anchors.fill: button
                    onClicked: {
                        button.buttonClicked()
                    }
                    objectName: "MyCustomButtonMouseArea"
                }
    
    }
    

    At first I had this inside the project I was working on. But I want to be able to register it as a custom component. So in order to do this, I tried to create a plugin from it. So I created a new project with qt quick2 plugin as a template.
    So the above code is now inside its own project. The custom button also contains some c++ code, which are also now inside the plugin project.
    MyCustomButton.hpp:

    #ifndef MYCUSTOMBUTTON_HPP
    #define MYCUSTOMBUTTON_HPP
    
    #include <QObject>
    #include <QtQuick/QQuickPaintedItem>
    
    class MyCustomButton : public QQuickPaintedItem
    {
        Q_OBJECT
        Q_PROPERTY(QString name READ name WRITE setName FINAL)
        Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
        QML_ELEMENT
    public:
        MyCustomButton(QQuickItem *parent = nullptr);
        void paint(QPainter *painter) override;
    
        QString name() const;
        void setName(const QString &name);
    
        QColor color() const;
        void setColor(const QColor &color);
    
        Q_INVOKABLE void buttonClicked();
    
        void changeValue();
    private:
        QString m_name;
        QColor m_color = Qt::red;
        bool m_value = false;
    
    public slots:
        void ButtonClicked();
    };
    
    #endif // MYCUSTOMBUTTON_HPP
    

    And the MyCustomButton.cpp

    #include "mycustombutton.h"
    #include <QPainter>
    #include <QDebug>
    
    MyCustomButton::MyCustomButton(QQuickItem *parent)
        : QQuickPaintedItem(parent)
    {
    
    }
    
    void MyCustomButton::paint(QPainter *painter)
    {
        QPen pen(m_color, 2);
        painter->setPen(pen);
        painter->setBrush(m_color);
    
        painter->setRenderHints(QPainter::Antialiasing, true);
        painter->drawEllipse(boundingRect().adjusted(1, 1, -1, -1));
    }
    
    QString MyCustomButton::name() const
    {
        return m_name;
    }
    
    void MyCustomButton::setName(const QString &name)
    {
        m_name = name;
    }
    
    QColor MyCustomButton::color() const
    {
        return m_color;
    }
    
    void MyCustomButton::setColor(const QColor &color)
    {
        m_color = color;
    }
    
    void MyCustomButton::buttonClicked()
    {
        qInfo() << "m_value before: " << m_value;
        m_value = !m_value;
        m_color = m_value ? Qt::green : Qt::red;
        update();
        qInfo() << "m_value after: " << m_value;
    }
    
    void MyCustomButton::changeValue()
    {
        buttonClicked();
    }
    
    void MyCustomButton::ButtonClicked()
    {
        buttonClicked();
    }
    

    It successfully builds. However, when I try to load the plugin from my other project, it is unable to load it.
    MyCustomButton.qml from other project:

    import QtQuick 6.6
    import QtQuick.Controls
    import QtQuick.Controls.Material
    // import MyCustomButton
    import com.wago.MyCustomButtinLibrary
    Item {
        width: 300; height: 200
        objectName: "root item"
    
        MyCustomButton {
            id: button
            Material.background: Material.Red
            width: 50
            height: 50
            name: "test"
            objectName: "MyCustomButton"
    
        }
    }
    

    I get the following error

    module "com.wago.MyCustomButtinLibrary" is not installed 
    

    I tried to follow the tutorials mentioned in here, but unfortunately I was not successful. From what I understand, the custom plugin should be located in the installation path from QT. However, I was unable to find it in there. Anyone got any clue where this might go wrong?

    D 1 Reply Last reply 3 Apr 2024, 05:18
    0
    • M Mighty_Pig
      2 Apr 2024, 08:15

      I recently started learning QT6 for a project I am working on.
      I am trying to create a GUI that contains some buttons and eventually text boxes too. In order to create the buttons, I created my custom qml component.
      The code for this button is as following:

      import QtQuick 6.6
      import QtQuick.Controls
      import QtQuick.Controls.Material
      import MyCustomButton
      
      Item {
          width: 300; height: 200
          objectName: "root item"
      
          MyCustomButton {
              id: button
              Material.background: Material.Red
              width: 50
              height: 50
              name: "test"
              objectName: "MyCustomButton"
          }
      
          Text {
                      id: name
                      text: button.name // Bind to the parent's text property
                      color: "black"
                      anchors.centerIn: button // Center text within the button
                      objectName: "MyCustomButtonText"
                  }
          MouseArea {
                      id: mouseArea
                      anchors.fill: button
                      onClicked: {
                          button.buttonClicked()
                      }
                      objectName: "MyCustomButtonMouseArea"
                  }
      
      }
      

      At first I had this inside the project I was working on. But I want to be able to register it as a custom component. So in order to do this, I tried to create a plugin from it. So I created a new project with qt quick2 plugin as a template.
      So the above code is now inside its own project. The custom button also contains some c++ code, which are also now inside the plugin project.
      MyCustomButton.hpp:

      #ifndef MYCUSTOMBUTTON_HPP
      #define MYCUSTOMBUTTON_HPP
      
      #include <QObject>
      #include <QtQuick/QQuickPaintedItem>
      
      class MyCustomButton : public QQuickPaintedItem
      {
          Q_OBJECT
          Q_PROPERTY(QString name READ name WRITE setName FINAL)
          Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
          QML_ELEMENT
      public:
          MyCustomButton(QQuickItem *parent = nullptr);
          void paint(QPainter *painter) override;
      
          QString name() const;
          void setName(const QString &name);
      
          QColor color() const;
          void setColor(const QColor &color);
      
          Q_INVOKABLE void buttonClicked();
      
          void changeValue();
      private:
          QString m_name;
          QColor m_color = Qt::red;
          bool m_value = false;
      
      public slots:
          void ButtonClicked();
      };
      
      #endif // MYCUSTOMBUTTON_HPP
      

      And the MyCustomButton.cpp

      #include "mycustombutton.h"
      #include <QPainter>
      #include <QDebug>
      
      MyCustomButton::MyCustomButton(QQuickItem *parent)
          : QQuickPaintedItem(parent)
      {
      
      }
      
      void MyCustomButton::paint(QPainter *painter)
      {
          QPen pen(m_color, 2);
          painter->setPen(pen);
          painter->setBrush(m_color);
      
          painter->setRenderHints(QPainter::Antialiasing, true);
          painter->drawEllipse(boundingRect().adjusted(1, 1, -1, -1));
      }
      
      QString MyCustomButton::name() const
      {
          return m_name;
      }
      
      void MyCustomButton::setName(const QString &name)
      {
          m_name = name;
      }
      
      QColor MyCustomButton::color() const
      {
          return m_color;
      }
      
      void MyCustomButton::setColor(const QColor &color)
      {
          m_color = color;
      }
      
      void MyCustomButton::buttonClicked()
      {
          qInfo() << "m_value before: " << m_value;
          m_value = !m_value;
          m_color = m_value ? Qt::green : Qt::red;
          update();
          qInfo() << "m_value after: " << m_value;
      }
      
      void MyCustomButton::changeValue()
      {
          buttonClicked();
      }
      
      void MyCustomButton::ButtonClicked()
      {
          buttonClicked();
      }
      

      It successfully builds. However, when I try to load the plugin from my other project, it is unable to load it.
      MyCustomButton.qml from other project:

      import QtQuick 6.6
      import QtQuick.Controls
      import QtQuick.Controls.Material
      // import MyCustomButton
      import com.wago.MyCustomButtinLibrary
      Item {
          width: 300; height: 200
          objectName: "root item"
      
          MyCustomButton {
              id: button
              Material.background: Material.Red
              width: 50
              height: 50
              name: "test"
              objectName: "MyCustomButton"
      
          }
      }
      

      I get the following error

      module "com.wago.MyCustomButtinLibrary" is not installed 
      

      I tried to follow the tutorials mentioned in here, but unfortunately I was not successful. From what I understand, the custom plugin should be located in the installation path from QT. However, I was unable to find it in there. Anyone got any clue where this might go wrong?

      D Offline
      D Offline
      dheerendra
      Qt Champions 2022
      wrote on 3 Apr 2024, 05:18 last edited by
      #2

      @Mighty_Pig

      1. Create the directory called com/wago/MyCustomButtinLibrary
      2. Do you have qmldir with description of plugin ?
      3. Did you copy this to com/wago/MyCustomButtinLibrary ?
      4. Did you import the path where plugin is kept ?

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      M 1 Reply Last reply 4 Apr 2024, 07:36
      0
      • D dheerendra
        3 Apr 2024, 05:18

        @Mighty_Pig

        1. Create the directory called com/wago/MyCustomButtinLibrary
        2. Do you have qmldir with description of plugin ?
        3. Did you copy this to com/wago/MyCustomButtinLibrary ?
        4. Did you import the path where plugin is kept ?
        M Offline
        M Offline
        Mighty_Pig
        wrote on 4 Apr 2024, 07:36 last edited by
        #3

        @dheerendra

        Thank you for your help. I didn't know that if the URI is for example com.example.button that com and example were subfolders. I must have missed that somewhere.

        It was indeed not in subfolders, so I tried to add the subfolders without success.

        So I tried removing the subfolders and also setting the URI to MyCustomButton2.
        This works, however now I don't have the subfolders. However, I still want it to organize the components.

        So now my CMakeLists.txt looks the following:

        cmake_minimum_required(VERSION 3.16)
        
        project(MyCustomButton2 VERSION 0.1 LANGUAGES CXX)
        
        set(CMAKE_AUTOMOC ON)
        set(CMAKE_CXX_STANDARD_REQUIRED ON)
        set(QT_QML_OUTPUT_DIRECTORY  ${CMAKE_BINARY_DIR})
        
        find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
        
        qt_add_library(MyCustomButton2 STATIC)
        qt_add_qml_module(MyCustomButton2
            URI MyCustomButton2
            VERSION 1.0
            QML_FILES MyCustomButton2Controls.qml
            SOURCES mycustombutton2.cpp mycustombutton2.h
            SOURCES mycustombutton2.cpp
        )
        set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/plugins ${CMAKE_BINARY_DIR}/plugins CACHE STRING "" FORCE)
        
        set_target_properties(MyCustomButton2 PROPERTIES
            MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
            MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
            MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
            MACOSX_BUNDLE TRUE
            WIN32_EXECUTABLE TRUE
        )
        
        target_compile_definitions(MyCustomButton2
            PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
        target_link_libraries(MyCustomButton2
            PRIVATE Qt6::Quick)
        
        target_include_directories(MyCustomButton2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
        
        # Example Project
        qt_add_executable(ExampleProject example/example.cpp)
        qt_add_qml_module(ExampleProject
            URI ExampleProjectApp
            VERSION 1.0
            QML_FILES example/example.qml
        )
        target_link_libraries(ExampleProject PRIVATE Qt6::Quick MyCustomButton2plugin)
        target_compile_definitions(ExampleProject PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
        
        

        From what I understand, I only have to change the following line:

        qt_add_qml_module(MyCustomButton2
            URI MyCustomButton2
            VERSION 1.0
            QML_FILES MyCustomButton2Controls.qml
            SOURCES mycustombutton2.cpp mycustombutton2.h
            SOURCES mycustombutton2.cpp
        )
        

        To

        qt_add_qml_module(MyCustomButton2
            URI plugins.MyCustomButton2 #[[ Note I have changed this line]]
            VERSION 1.0
            QML_FILES MyCustomButton2Controls.qml
            SOURCES mycustombutton2.cpp mycustombutton2.h
            SOURCES mycustombutton2.cpp
        )
        

        In the example.cpp I have changed

        Q_IMPORT_QML_PLUGIN(MyCustomButton2Plugin)
        

        to

        Q_IMPORT_QML_PLUGIN(plugins_MyCustomButton2Plugin)
        

        and finally I changed inside the example.qml this line:

        import MyCustomButton2
        

        to

        import plugins.MyCustomButton2
        

        The folder structure looks like this:
        a77910d8-0ae4-4003-af27-6580dc2b1411-image.png

        However, when I try to run it I get the following error:

        09:32:28: Starting C:\Users\dismienk\Documents\build-MyCustomButton2-Desktop_Qt_6_6_2_MinGW_64_bit-Debug\ExampleProject.exe...
        
        QQmlApplicationEngine failed to load component
        qrc:/ExampleProjectApp/example/example.qml:13:5: Type MyCustomButton2Controls unavailable
        qrc:/plugins/MyCustomButton2/MyCustomButton2Controls.qml:4:1: module "MyCustomButton2" plugin "MyCustomButton2plugin" not found
        

        I also followed the following page. I set the path as following

        set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/plugins ${CMAKE_BINARY_DIR}/plugins CACHE STRING "" FORCE)
        

        This fixed the issue inside the Qt Creator itself (I got a warning that it was unable to find the plugin), but unfortunately not when running the program.

        Again, thank you for your time to help me :)

        M 1 Reply Last reply 5 Apr 2024, 07:14
        0
        • M Mighty_Pig
          4 Apr 2024, 07:36

          @dheerendra

          Thank you for your help. I didn't know that if the URI is for example com.example.button that com and example were subfolders. I must have missed that somewhere.

          It was indeed not in subfolders, so I tried to add the subfolders without success.

          So I tried removing the subfolders and also setting the URI to MyCustomButton2.
          This works, however now I don't have the subfolders. However, I still want it to organize the components.

          So now my CMakeLists.txt looks the following:

          cmake_minimum_required(VERSION 3.16)
          
          project(MyCustomButton2 VERSION 0.1 LANGUAGES CXX)
          
          set(CMAKE_AUTOMOC ON)
          set(CMAKE_CXX_STANDARD_REQUIRED ON)
          set(QT_QML_OUTPUT_DIRECTORY  ${CMAKE_BINARY_DIR})
          
          find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
          
          qt_add_library(MyCustomButton2 STATIC)
          qt_add_qml_module(MyCustomButton2
              URI MyCustomButton2
              VERSION 1.0
              QML_FILES MyCustomButton2Controls.qml
              SOURCES mycustombutton2.cpp mycustombutton2.h
              SOURCES mycustombutton2.cpp
          )
          set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/plugins ${CMAKE_BINARY_DIR}/plugins CACHE STRING "" FORCE)
          
          set_target_properties(MyCustomButton2 PROPERTIES
              MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
              MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
              MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
              MACOSX_BUNDLE TRUE
              WIN32_EXECUTABLE TRUE
          )
          
          target_compile_definitions(MyCustomButton2
              PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
          target_link_libraries(MyCustomButton2
              PRIVATE Qt6::Quick)
          
          target_include_directories(MyCustomButton2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
          
          # Example Project
          qt_add_executable(ExampleProject example/example.cpp)
          qt_add_qml_module(ExampleProject
              URI ExampleProjectApp
              VERSION 1.0
              QML_FILES example/example.qml
          )
          target_link_libraries(ExampleProject PRIVATE Qt6::Quick MyCustomButton2plugin)
          target_compile_definitions(ExampleProject PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
          
          

          From what I understand, I only have to change the following line:

          qt_add_qml_module(MyCustomButton2
              URI MyCustomButton2
              VERSION 1.0
              QML_FILES MyCustomButton2Controls.qml
              SOURCES mycustombutton2.cpp mycustombutton2.h
              SOURCES mycustombutton2.cpp
          )
          

          To

          qt_add_qml_module(MyCustomButton2
              URI plugins.MyCustomButton2 #[[ Note I have changed this line]]
              VERSION 1.0
              QML_FILES MyCustomButton2Controls.qml
              SOURCES mycustombutton2.cpp mycustombutton2.h
              SOURCES mycustombutton2.cpp
          )
          

          In the example.cpp I have changed

          Q_IMPORT_QML_PLUGIN(MyCustomButton2Plugin)
          

          to

          Q_IMPORT_QML_PLUGIN(plugins_MyCustomButton2Plugin)
          

          and finally I changed inside the example.qml this line:

          import MyCustomButton2
          

          to

          import plugins.MyCustomButton2
          

          The folder structure looks like this:
          a77910d8-0ae4-4003-af27-6580dc2b1411-image.png

          However, when I try to run it I get the following error:

          09:32:28: Starting C:\Users\dismienk\Documents\build-MyCustomButton2-Desktop_Qt_6_6_2_MinGW_64_bit-Debug\ExampleProject.exe...
          
          QQmlApplicationEngine failed to load component
          qrc:/ExampleProjectApp/example/example.qml:13:5: Type MyCustomButton2Controls unavailable
          qrc:/plugins/MyCustomButton2/MyCustomButton2Controls.qml:4:1: module "MyCustomButton2" plugin "MyCustomButton2plugin" not found
          

          I also followed the following page. I set the path as following

          set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/plugins ${CMAKE_BINARY_DIR}/plugins CACHE STRING "" FORCE)
          

          This fixed the issue inside the Qt Creator itself (I got a warning that it was unable to find the plugin), but unfortunately not when running the program.

          Again, thank you for your time to help me :)

          M Offline
          M Offline
          Mighty_Pig
          wrote on 5 Apr 2024, 07:14 last edited by
          #4

          So I solved the issue kind of. Instead of having 2 different project, I just moved them to 1 single project and now it works. I have another issue, but I'll make a new thread since this one is solved.

          1 Reply Last reply
          0
          • M Mighty_Pig has marked this topic as solved on 5 Apr 2024, 07:14

          1/4

          2 Apr 2024, 08:15

          • Login

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