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. Simple line drawing by using a paint object
Forum Updated to NodeBB v4.3 + New Features

Simple line drawing by using a paint object

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 2 Posters 723 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.
  • S Offline
    S Offline
    Shadow.01
    wrote on last edited by
    #1

    Hi all,
    I have a container.qml view and a container.cpp class, with his header container.h. I want draw a simple line in the qml view, but this time I want do it by using a paint object I already created in container.cpp class. Unfortunately doesn't work; I think, I have done some mistake by connecting the cpp class to the qml view.

    The class line should be correct:

    #include "container.h"
    #include <QPainter>
    
    class DrawElement : public QQuickPaintedItem
    {
        void paint(QPainter *painter)
        {
            QBrush brush(Qt::cyan);
            painter->setBrush(brush);
            painter->setPen(Qt::NoPen);
            painter->setRenderHint(QPainter::Antialiasing);
            painter->drawLine(0, 0, 200, 200);
        }
    };
    

    This is the container.h code:

    #ifndef CONTAINER_H
    #define CONTAINER_H
    
    #include <QQuickPaintedItem>
    #include <QObject>
    
    class container : public QQuickPaintedItem
    {
    public:
        container();
        void paint();
    };
    
    #endif // CONTAINER_H
    

    And this is the container.qml code (if I try to import here the container.h file, I receive an error about "no such directory"):

    import QtQuick 2.0
    
    Window {
        width: 640
        height: 480
        visible: true
        title: qsTr("Container page")
    
        Rectangle{
            height: 50
            width: 100
            color: "#ffffff"
        }
    }
    

    I tried to be more detailed as possible, could someone tell me please why I can't import the desired c++ class into my QML? Thank you very much

    KroMignonK 1 Reply Last reply
    0
    • S Shadow.01

      Hi all,
      I have a container.qml view and a container.cpp class, with his header container.h. I want draw a simple line in the qml view, but this time I want do it by using a paint object I already created in container.cpp class. Unfortunately doesn't work; I think, I have done some mistake by connecting the cpp class to the qml view.

      The class line should be correct:

      #include "container.h"
      #include <QPainter>
      
      class DrawElement : public QQuickPaintedItem
      {
          void paint(QPainter *painter)
          {
              QBrush brush(Qt::cyan);
              painter->setBrush(brush);
              painter->setPen(Qt::NoPen);
              painter->setRenderHint(QPainter::Antialiasing);
              painter->drawLine(0, 0, 200, 200);
          }
      };
      

      This is the container.h code:

      #ifndef CONTAINER_H
      #define CONTAINER_H
      
      #include <QQuickPaintedItem>
      #include <QObject>
      
      class container : public QQuickPaintedItem
      {
      public:
          container();
          void paint();
      };
      
      #endif // CONTAINER_H
      

      And this is the container.qml code (if I try to import here the container.h file, I receive an error about "no such directory"):

      import QtQuick 2.0
      
      Window {
          width: 640
          height: 480
          visible: true
          title: qsTr("Container page")
      
          Rectangle{
              height: 50
              width: 100
              color: "#ffffff"
          }
      }
      

      I tried to be more detailed as possible, could someone tell me please why I can't import the desired c++ class into my QML? Thank you very much

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by KroMignon
      #2

      @Shadow-01 said in Simple line drawing by using a paint object:

      could someone tell me please why I can't import the desired c++ class into my QML?

      Because you have to register it before.
      There are 2 way to do it:

      • with QML_ELEMENT (Qt 5.15 or higher required) => https://doc.qt.io/qt-5/qtqml-cppintegration-topic.html
      • with qmlRegisterType() (any Qt version)=> https://qmlbook.github.io/ch18-extensions/extensions.html

      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

      1 Reply Last reply
      2
      • S Offline
        S Offline
        Shadow.01
        wrote on last edited by
        #3

        First of all, thanks for your link. I choosen the first solution. In the link you sent me I understand almost all and all is done as indicated except the point 3: if I add the indicated lines, I see an error. I think, the reason is that my app is done in cmake and not qmake, so the project file is a little bit different. To be totally clear, I sent below my project file in order to ask, how can I edit it in order to make visible also my "container" class? Thanks!

        cmake_minimum_required(VERSION 3.14)
        
        project(myApp VERSION 0.1 LANGUAGES CXX)
        
        set(CMAKE_INCLUDE_CURRENT_DIR ON)
        
        set(CMAKE_AUTOUIC ON)
        set(CMAKE_AUTOMOC ON)
        set(CMAKE_AUTORCC ON)
        
        set(CMAKE_CXX_STANDARD 17)
        set(CMAKE_CXX_STANDARD_REQUIRED ON)
        
        find_package(QT NAMES Qt6 COMPONENTS Core Quick REQUIRED)
        find_package(Qt6 COMPONENTS Core Quick REQUIRED)
        
        set(PROJECT_SOURCES
                main.cpp
                qml.qrc
                home.h
                home.cpp
                container.h
                container.cpp
        )
        
        qt_add_executable(myApp    MANUAL_FINALIZATION
            ${PROJECT_SOURCES}
        )
        
        target_compile_definitions(myApp
          PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
        target_link_libraries(myApp
          PRIVATE Qt6::Core Qt6::Quick)
        
        set_target_properties(myApp PROPERTIES
            QT_QML_MODULE_VERSION 1.0
            QT_QML_MODULE_URI me.myApp
        )
        
        list(APPEND QML_IMPORT_PATH .)
        
        qt6_qml_type_registration(myApp)
        qt_import_qml_plugins(myApp)
        qt_finalize_executable(myApp)```
        KroMignonK 1 Reply Last reply
        0
        • S Shadow.01

          First of all, thanks for your link. I choosen the first solution. In the link you sent me I understand almost all and all is done as indicated except the point 3: if I add the indicated lines, I see an error. I think, the reason is that my app is done in cmake and not qmake, so the project file is a little bit different. To be totally clear, I sent below my project file in order to ask, how can I edit it in order to make visible also my "container" class? Thanks!

          cmake_minimum_required(VERSION 3.14)
          
          project(myApp VERSION 0.1 LANGUAGES CXX)
          
          set(CMAKE_INCLUDE_CURRENT_DIR ON)
          
          set(CMAKE_AUTOUIC ON)
          set(CMAKE_AUTOMOC ON)
          set(CMAKE_AUTORCC ON)
          
          set(CMAKE_CXX_STANDARD 17)
          set(CMAKE_CXX_STANDARD_REQUIRED ON)
          
          find_package(QT NAMES Qt6 COMPONENTS Core Quick REQUIRED)
          find_package(Qt6 COMPONENTS Core Quick REQUIRED)
          
          set(PROJECT_SOURCES
                  main.cpp
                  qml.qrc
                  home.h
                  home.cpp
                  container.h
                  container.cpp
          )
          
          qt_add_executable(myApp    MANUAL_FINALIZATION
              ${PROJECT_SOURCES}
          )
          
          target_compile_definitions(myApp
            PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
          target_link_libraries(myApp
            PRIVATE Qt6::Core Qt6::Quick)
          
          set_target_properties(myApp PROPERTIES
              QT_QML_MODULE_VERSION 1.0
              QT_QML_MODULE_URI me.myApp
          )
          
          list(APPEND QML_IMPORT_PATH .)
          
          qt6_qml_type_registration(myApp)
          qt_import_qml_plugins(myApp)
          qt_finalize_executable(myApp)```
          KroMignonK Offline
          KroMignonK Offline
          KroMignon
          wrote on last edited by KroMignon
          #4

          @Shadow-01 said in Simple line drawing by using a paint object:

          This should be change

           set_target_properties(myApp PROPERTIES
               QT_QML_MODULE_VERSION 1.0
               QT_QML_MODULE_URI me.myApp
           )
           
           qt6_qml_type_registration(myApp)
           qt_import_qml_plugins(myApp)
          

          to

          set_target_properties(container PROPERTIES
              QT_QML_MODULE_VERSION 1.0
              QT_QML_MODULE_URI     me.myApp
          )
          
          qt6_qml_type_registration(container)
          

          And in your QML:

          import me.myApp // container should be available
          

          As side note: C++ class name should be UpperCamelCase to be Qt naming convention comform. The class name should be Container and not container.

          EDIT: I never use cmake, so I am not 100% sure of this. I don't know if QML_ELEMENT is good integrated in cmake or if it only works with qmake.

          If it don"t work, I would recommand you to prefere qmlRegisterType() which always works:

          • with all Qt version
          • with all build systems.

          It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

          1 Reply Last reply
          2
          • S Offline
            S Offline
            Shadow.01
            wrote on last edited by Shadow.01
            #5

            Ok, thanks, I already solved it. It's only enough to import the class name in the project sources list and nothing else. The mistakes appeared because I searched also to import the single class.

            Now, a big part of the question is solved and what I need now is: how can I create inside a paint function a line drawing?

            KroMignonK 1 Reply Last reply
            0
            • S Shadow.01

              Ok, thanks, I already solved it. It's only enough to import the class name in the project sources list and nothing else. The mistakes appeared because I searched also to import the single class.

              Now, a big part of the question is solved and what I need now is: how can I create inside a paint function a line drawing?

              KroMignonK Offline
              KroMignonK Offline
              KroMignon
              wrote on last edited by KroMignon
              #6

              @Shadow-01 said in Simple line drawing by using a paint object:

              class which gives me a "hello world" message, that I can use in a QML file?

              Do you have read documentation about C++ integration with QML?

              • https://doc.qt.io/qt-5/qtqml-cppintegration-overview.html

              Create a simple QObject based class:

              class Backend: public QObject
              {
                  Q_OBJECT
              
                  Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
              
              public:
                  void setAuthor(const QString &a) {
                      if (a != m_author) {
                          m_author = a;
                          emit authorChanged();
                      }
                  }
                  
                  QString author() const {
                      return m_author;
                  }
                  
              signals:
                  void authorChanged();
                  
              private:
                  QString m_author;
              };
              

              A simple main:

              int main(int argc, char *argv[])
              {
                  QGuiApplication app(argc, argv);
              
                  QQuickView view;
                  Backend backend;
                  view.engine()->rootContext()->setContextProperty("backend", &backend);
                  view.setSource(QUrl::fromLocalFile("MyItem.qml"));
                  view.show();
              
                  return app.exec();
              }
              

              And the MyItem.qml

              import QtQuick 2.0
              
              Text {
                  width: 100; height: 100
                  text: backend.author    // invokes Backend::author() to get this value
              
                  Component.onCompleted: {
                      backend.author = "Jonah"  // invokes Backend::setAuthor()
                  }
              }
              

              [EDIT]
              Or for more "fun", you can change the main as follow:

              int main(int argc, char *argv[])
              {
                  QGuiApplication app(argc, argv);
              
                  QQuickView view;
                  Backend backend;
                  view.engine()->rootContext()->setContextProperty("backend", &backend);
                  view.setSource(QUrl::fromLocalFile("MyItem.qml"));
                  view.show();
                  
                  QTimer tmr;
                  QObject::connect(&tmr, &QTimer::timeout, [&](){
                     backend.setAuthor(QDateTime::currentDateTime().toString("dd/MM/yyyy  hh:mm:ss.zzz"));
                     tmr.start(100);
                  });
                  tmr.setSingleShot(true);
                  tmr.start(10);
              
                  return app.exec();
              }
              

              It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

              1 Reply Last reply
              0
              • S Offline
                S Offline
                Shadow.01
                wrote on last edited by
                #7

                Thank you very much! You reply during my answer, you was really fast. I try now your last reply.

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  Shadow.01
                  wrote on last edited by Shadow.01
                  #8

                  Ok, thanks to your indications. The question is now absolutely easier and I have isolated the 90% of the problem. So, I have now a container.ccp class:

                  #include "profileview.h"
                  #include <QPainter>
                  
                  ProfileView::ProfileView()
                  {
                  }
                  
                  void ProfileView::paint(QPainter *painter) {
                  
                      QBrush brush(Qt::cyan);
                      painter->setBrush(brush);
                      painter->setPen(Qt::NoPen);
                      painter->setRenderHint(QPainter::Antialiasing);
                      painter->drawLine(0, 0, 200, 200);
                  }
                  

                  with the corrispondent header:

                  #ifndef CONTAINER_H
                  #define CONTAINER_H
                  
                  #include <QQuickPaintedItem>
                  #include <QObject>
                  
                  class container : public QQuickPaintedItem
                  {
                  
                  
                  public:
                      container();
                      void paint();
                  
                  };
                  
                  #endif // CONTAINER_H
                  

                  And this is the way I am using to call it in the qml:

                  import QtQuick 2.0
                  import com.me.myApp
                  
                  Window {
                      width: 640
                      height: 480
                      visible: true
                      title: qsTr("Container page")
                  
                      Rectangle{
                          height: 50
                          width: 100
                          color: "#ffffff"
                      }
                  
                      //Here the paint calling
                      ProfileView {
                  
                          id: newCanvas
                          anchors.fill: parent
                      }
                  }
                  

                  Now, my class is perfectly visible in my container.qml (if I try to write the name of the void, I don't see any error; by changing the name, the name is not accepted. The last question is: how can I "consume" in my qml view the paint function of my class, so I can see in the qml the line I have defined in the class?

                  Really thank you very much!

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    Shadow.01
                    wrote on last edited by
                    #9

                    Thanks all, post solved. I put the correct properties on the paint area and I deleted any other element from the background (it was also a problem of depth level).

                    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