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
Forum Updated to NodeBB v4.3 + New Features

Register custom qml component using plugins

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 2 Posters 578 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 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?

    dheerendraD 1 Reply Last reply
    0
    • M Mighty_Pig

      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?

      dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on 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
      0
      • dheerendraD dheerendra

        @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 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
        0
        • M Mighty_Pig

          @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 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

          • Login

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