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. Feasability study: Displaying a graph with QML ?
Forum Updated to NodeBB v4.3 + New Features

Feasability study: Displaying a graph with QML ?

Scheduled Pinned Locked Moved QML and Qt Quick
29 Posts 7 Posters 17.9k Views 1 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.
  • sierdzioS Offline
    sierdzioS Offline
    sierdzio
    Moderators
    wrote on last edited by
    #5

    QML is integral part of Qt. Better to differentiate between QtWidgets and QtQuick/QML.

    The answer is: I don't know. Try making test projects using both technologies and then decide. There is no built-in mechanism that will allow you to create this in a couple lines of code. I would personally recommend QML, as it's easy and fast but you have to judge yourself.

    You can also take a look at Qwt, maybe Uwe has some classes there that would help you. I think it's a charting library, but have never tried - it's quite probable there is some graphing stuff there, too.

    (Z(:^

    1 Reply Last reply
    0
    • Z Offline
      Z Offline
      Zaxy
      wrote on last edited by
      #6

      Why do you recommend QML ? Is it easier to be done with QML ? For QML, which elements you could advise me to use or even if you have a simular tutorial on that ?

      Thanks again

      1 Reply Last reply
      0
      • sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by
        #7

        "QML, as it's easy and fast" :) It's a pure pleasure to code in. Lame reason, I know, but a valid one for me. There are components like Image, Transform and various Paths that can make it quite straightforward to code, although there are caveats, too. That is why I'm not sure what to recommend to you.

        No I don't have any tutorials at hand. Search the documentation.

        (Z(:^

        1 Reply Last reply
        0
        • Z Offline
          Z Offline
          Zaxy
          wrote on last edited by
          #8

          Thanks a lot, sierdzio !

          Anyone else has an idea ?

          1 Reply Last reply
          0
          • N Offline
            N Offline
            nizeguy
            wrote on last edited by
            #9

            Try porting some small js library that already does that to html canvas and tell us about it.

            If it can't be done easily in javascript qml for some reason, it can surely be done in QtQuick in C++ .

            ps: just found this one in reddit/programming : http://tenxer.github.com/xcharts/examples/

            1 Reply Last reply
            0
            • Z Offline
              Z Offline
              Zaxy
              wrote on last edited by
              #10

              Hello,

              I have the following example - a QList of Nodes in ConfigurationModel .
              I want to bind the properties "QString nodeID" and "QString iconFilePath" beween the QML component Node and the C++ class Node.

              Unfortunetly the binding is not working - when you create the Node instances from C++, the properties of the correspondingly generated QML objects don't have the given values. They are empty. I cannot find where the issue comes from ... Could you please advise me, what I do wrong ?

              main.qml
              @import QtQuick 1.0

              Rectangle {
              width: 500
              height: 500

              Repeater {
                  anchors.fill: parent
                  model: configModel
                  delegate: Node {}
              }
              

              }
              @

              Node.qml
              @import QtQuick 1.0
              import NodeLib 1.0

              Node {
              id: nodeDelegate

              Image{
                  id : nodeIcon
                  source: nodeDelegate.iconFilePath
              }
              
              Text {
                 anchors.top: nodeIcon.bottom
                 text: nodeDelegate.nodeID
              }
              
              MouseArea {
                 anchors.fill: parent
              }
              

              }
              @

              main.cpp
              @#include <QApplication>
              #include "qmlapplicationviewer.h"
              #include <QDeclarativeContext>
              #include <QtDeclarative>

              #include "ConfigurationModel.h"

              Q_DECL_EXPORT int main(int argc, char *argv[])
              {
              QScopedPointer<QApplication> app(createApplication(argc, argv));

              QDeclarativeView    declarativeView;
              qmlRegisterType<Node>("NodeLib", 1, 0, "Node");
              
              ConfigurationModel* p_configModel = ConfigurationModel::GetConfigModelInstance();
              p_configModel->addNodeInConfigurationModel(new Node("PanelXXXX", PLUG_IN, EVALUATION_BLOCK, "./ui-images/cutetube.png"));
              p_configModel->addNodeInConfigurationModel(new Node("PanelYYYY", PLUG_IN, EVALUATION_BLOCK, "./ui-images/cutetube.png"));
              Node *p_nodeZ = new Node("PanelZZZZ", PLUG_IN, EVALUATION_BLOCK, "./ui-images/cutetube.png");
              p_nodeZ->setNodeID("NODE ZZZZ");
              p_configModel->addNodeInConfigurationModel(p_nodeZ);
              
              // if the configuration has been changed, you need to call setContextProperty() again to update the QML view
              
              declarativeView.rootContext()->setContextProperty("configModel", ConfigurationModel::GetConfigModelInstance());
              
              declarativeView.setSource(QUrl::fromLocalFile&#40;"qml/ConfigurationView/main.qml"&#41;);
              declarativeView.show();
              
              return app->exec&#40;&#41;;
              

              }
              @

              1 Reply Last reply
              0
              • Z Offline
                Z Offline
                Zaxy
                wrote on last edited by
                #11

                Node.h
                @#ifndef NODE_H
                #define NODE_H

                #include <QString>
                #include <QList>
                #include <QDeclarativeItem>

                #include "GlobalDeclarations.h"

                // Inherit from QDeclarativeItem in order to override paint() method and to display links to parent nodes
                class Node : public QDeclarativeItem
                {
                Q_OBJECT
                Q_PROPERTY(QString iconFilePath READ getIconFilePath WRITE setIconFilePath NOTIFY iconFilePathChanged)
                Q_PROPERTY(QString nodeID READ getNodeID WRITE setNodeID NOTIFY nodeIDchanged)

                public:
                // Constructors
                Node();
                Node(QString nodeID, NodeType nodeType, PlugInType plugInType, QString iconFilePath);

                 QHash<int, QByteArray> roleNames() const;
                // Destructor
                ~Node();
                
                QString getNodeID() const;
                Q_INVOKABLE bool setNodeID(const QString &nodeID);
                
                QString  getIconFilePath() const;
                Q_INVOKABLE bool setIconFilePath(const QString &iconFilePath);
                
                void hide();
                void show();
                
                void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
                

                signals:
                void nodeIDchanged(QString data);
                void iconFilePathChanged(QString data);
                void dataChanged();

                private:
                QString _nodeID;
                NodeType _nodeType;
                PlugInType _plugInType;
                QString _iconFilePath;

                QList<Node*>    _parents;
                QList<Node*>    _children;
                

                };

                #endif // NODE_H
                @

                1 Reply Last reply
                0
                • Z Offline
                  Z Offline
                  Zaxy
                  wrote on last edited by
                  #12

                  ConfigurationModel.h
                  @#ifndef CONFIGURATIONVIEW_H
                  #define CONFIGURATIONVIEW_H

                  #include <QList>
                  #include <QDeclarativeItem>
                  #include <QAbstractListModel>

                  #include "Node.h"

                  // This class is implemented as Singleton
                  class ConfigurationModel : public QAbstractListModel
                  {

                  Q_OBJECT
                  

                  public:

                  // Destructor
                  ~ConfigurationModel();
                  
                  static ConfigurationModel* GetConfigModelInstance ();
                  
                  void addNodeInConfigurationModel(Node *p_node);
                  QList< Node* >&  accessAllNodes();
                  const QList< Node* >&  getAllNodes() const;
                  void removeNodeFromConfigurationModel(Node *p_node);
                  
                  QModelIndex indexFromItem(const Node *item) const;
                  
                  // Functions from QAbstractListModel that should be implemented
                  int rowCount(const QModelIndex &parent) const;
                  QVariant data(const QModelIndex &index, int role) const;
                  

                  signals:
                  void dataChanged();

                  private slots:
                  void handleItemChange();

                  private:
                  // Constructor
                  explicit ConfigurationModel(QObject* parent = 0);

                  // Copy constructor
                  ConfigurationModel(const ConfigurationModel& sourceConfView) {}
                  
                  // Assignment operator
                  ConfigurationModel& operator=(const ConfigurationModel& sourceConfView) {}
                  
                  static ConfigurationModel*       _pConfigModelInstance;
                  
                  QList< Node* >                  _rootNodes;
                  QList< Node* >                  _standAloneNodes;
                  QList< Node* >                  _allNodes;
                  

                  };

                  #endif // CONFIGURATIONVIEW_H
                  @

                  1 Reply Last reply
                  0
                  • Z Offline
                    Z Offline
                    Zaxy
                    wrote on last edited by
                    #13

                    Node.cpp
                    @#include <Node.h>

                    // Constructors
                    Node::Node() : _nodeID(""), _nodeType(NOT_DEFINED), _plugInType(NOT_DEFINEDD), _iconFilePath("")
                    {
                    setFlag(ItemHasNoContents, false);
                    }

                    Node::Node(QString nodeID, NodeType nodeType, PlugInType plugInType, QString iconFilePath) :
                    QDeclarativeItem (), _nodeID(nodeID), _nodeType(nodeType), _plugInType(plugInType), _iconFilePath(iconFilePath)
                    {
                    emit nodeIDchanged(_nodeID);
                    emit iconFilePathChanged(_iconFilePath);
                    emit dataChanged();

                    setFlag(ItemHasNoContents, false);
                    

                    }

                    // Destructor
                    Node::~Node()
                    {
                    }

                    QHash<int, QByteArray> Node::roleNames() const
                    {
                    QHash<int, QByteArray> names;
                    names[Qt::UserRole + 1] = "name";
                    return names;
                    }

                    QString Node::getNodeID() const
                    {
                    return _nodeID;
                    }

                    bool Node::setNodeID(const QString &nodeID)
                    {
                    _nodeID = nodeID;
                    emit nodeIDchanged(_nodeID);
                    emit dataChanged();

                    return true;
                    

                    }

                    QString Node::getIconFilePath() const
                    {
                    return _iconFilePath;
                    }

                    bool Node::setIconFilePath(const QString &iconFilePath)
                    {
                    _iconFilePath = iconFilePath;
                    emit iconFilePathChanged(_iconFilePath);
                    emit dataChanged();

                    return true;
                    

                    }
                    @

                    1 Reply Last reply
                    0
                    • Z Offline
                      Z Offline
                      Zaxy
                      wrote on last edited by
                      #14

                      ConfigurationModel.cpp
                      @#include "ConfigurationModel.h"

                      // The global static instance of the Singleton
                      ConfigurationModel* ConfigurationModel::_pConfigModelInstance = NULL;

                      // Constructor
                      ConfigurationModel::ConfigurationModel(QObject *parent) :
                      QAbstractListModel(parent)
                      {
                      }

                      // Destructor
                      ConfigurationModel::~ConfigurationModel()
                      {

                      // free memory allocated for all nodes of the given configuration
                      for (QList<Node*>::iterator itAllNodesList = _pConfigModelInstance->_allNodes.begin();
                           itAllNodesList != _pConfigModelInstance->_allNodes.end();
                           itAllNodesList++)
                      {
                          delete  *itAllNodesList;
                          *itAllNodesList = NULL;
                      }
                      
                      // free memory of the ConfigurationView instance itself
                      delete _pConfigModelInstance;
                      _pConfigModelInstance = NULL;
                      

                      }

                      // The class ConfigurationView is implemented as Singleton.
                      // GetConfigModelInstance() is a static method.
                      ConfigurationModel* ConfigurationModel::GetConfigModelInstance ()
                      {
                      if (_pConfigModelInstance == NULL)
                      {

                          _pConfigModelInstance = new ConfigurationModel();
                      }
                      
                      return _pConfigModelInstance;
                      

                      }

                      void ConfigurationModel::addNodeInConfigurationModel(Node *p_node)
                      {
                      beginInsertRows(QModelIndex(), rowCount(QModelIndex()), rowCount(QModelIndex())); // QModelIndex() is a dummy parameter, not used actually
                      connect(p_node, SIGNAL(dataChanged()),this, SLOT(handleItemChange()));

                      _allNodes.append(p_node);
                      
                      endInsertRows();
                      
                      // ...
                      refreshView();
                      

                      }

                      QList<Node*>& ConfigurationModel::accessAllNodes()
                      {
                      return _allNodes;
                      }

                      const QList<Node*>& ConfigurationModel::getAllNodes() const
                      {
                      return _allNodes;
                      }

                      void ConfigurationModel::removeNodeFromConfigurationModel(Node *p_node)
                      {
                      // ...
                      refreshView();
                      }

                      QModelIndex ConfigurationModel::indexFromItem(const Node *item) const
                      {
                      Q_ASSERT(item);
                      for(int row = 0; row < _allNodes.size(); row++) {
                      if(_allNodes.at(row) == item) return index(row);
                      }
                      return QModelIndex();
                      }

                      void ConfigurationModel::handleItemChange()
                      {
                      Node* node = static_cast<Node*>(sender());
                      QModelIndex index = indexFromItem(node);
                      if(index.isValid())
                      emit dataChanged();
                      }

                      // Functions from QAbstractListView that should be implemented
                      int ConfigurationModel::rowCount(const QModelIndex &parent) const
                      {
                      Q_UNUSED(parent);
                      return _allNodes.size();
                      }

                      QVariant ConfigurationModel::data(const QModelIndex &index, int role) const
                      {
                      if(index.row() < 0 || index.row() >= _allNodes.size())
                      return QVariant();

                      if(role == (Qt::UserRole + 1))
                          return _allNodes.at(index.row())->getNodeID();
                      return QVariant();
                      

                      }
                      @

                      1 Reply Last reply
                      0
                      • sierdzioS Offline
                        sierdzioS Offline
                        sierdzio
                        Moderators
                        wrote on last edited by
                        #15

                        I'm sorry, but are you insane? Do you really expect me to read all this?

                        @
                        Node {
                        id: nodeDelegate

                        Image{
                            id : nodeIcon
                            source: nodeDelegate.iconFilePath // no need for referencing nodeDelegate
                        }
                        
                        Text {
                           anchors.top: nodeIcon.bottom
                           text: nodeDelegate.nodeID // no need for referencing nodeDelegate
                        }
                        

                        }
                        @

                        I suspect you must feed the delegate with entries from the model. Debug, or better - create a small, dumb example to get the hang of Repeater.

                        Also, I would suggest making node connections separately, not by overriding ::paint().

                        (Z(:^

                        1 Reply Last reply
                        0
                        • Z Offline
                          Z Offline
                          Zaxy
                          wrote on last edited by
                          #16

                          Exactly, I want to feed the delegate with entries from the model by using the Q_Property binding in Node.h

                          The example is not complicated, but the binding is not working, and I cannot find why.

                          If I have Q_PROPERTIes like this:

                          @class Node : public QDeclarativeItem
                          {
                          Q_OBJECT
                          Q_PROPERTY(QString iconFilePath READ getIconFilePath WRITE setIconFilePath NOTIFY iconFilePathChanged)
                          Q_PROPERTY(QString nodeID READ getNodeID WRITE setNodeID NOTIFY nodeIDchanged)
                          @

                          How should I refer to them in the QML component Node ?
                          Is the following correct:

                          @import QtQuick 1.0
                          import NodeLib 1.0

                          Node {
                          id: nodeDelegate

                          Image{
                              id : nodeIcon
                              source: nodeDelegate.iconFilePath
                          }
                          
                          Text {
                             anchors.top: nodeIcon.bottom
                             text: nodeDelegate.nodeID
                          }
                          
                          MouseArea {
                             anchors.fill: parent
                          }
                          

                          }
                          @

                          1 Reply Last reply
                          0
                          • sierdzioS Offline
                            sierdzioS Offline
                            sierdzio
                            Moderators
                            wrote on last edited by
                            #17

                            You inherit from Node.h, so the properties are visible in QML without refering to the id. Instead of "source: nodeDelegate.iconFilePath" you can just write "iconFilePath". But that has nothing to do with the model - that just assigns the value set in c++.

                            To access the model, you need to use variables declared in the model. See "this page":http://doc-snapshot.qt-project.org/4.8/qdeclarativemodels.html for reference.

                            (Z(:^

                            1 Reply Last reply
                            0
                            • Z Offline
                              Z Offline
                              Zaxy
                              wrote on last edited by
                              #18

                              Hi Sierdzio,

                              Thanks for the article. I implemented a model with nodeID and iconFilePath roles and now I can display the Node objects in a GridView for example or in a Repeater.

                              But I need a way to draw the graph on the screen:
                              - order the Node objects in a suitable way on the screen - how could I place the objects in a custom way ? Is there something like currentNode.left = previousNode.right etc. ?
                              - draw connection lines between some nodes - for that could I use the paint function ?

                              Thanks again for the help !

                              1 Reply Last reply
                              0
                              • sierdzioS Offline
                                sierdzioS Offline
                                sierdzio
                                Moderators
                                wrote on last edited by
                                #19

                                I would use QML Rectangle for that. If you want to detect things like previousnode.right, you need to implement it yourself. You could base this on meta object's parent and children properties if you wish.

                                Or, of course, you can use your own paint function.

                                (Z(:^

                                1 Reply Last reply
                                0
                                • Z Offline
                                  Z Offline
                                  Zaxy
                                  wrote on last edited by
                                  #20

                                  So , to use the paint function to draw a line between two nodes.

                                  And about displaying the QList<Node*> in a customized way - for example in a tree view, what could I do ? I think, whan a new node is added to the list, it is automatically displayed, but I want somehow to re-order the graphical representation. I have also additional llist, containing the root Node(s), so I could visit all tree nodes, but don't know how to display them node by node and place them on the screen.

                                  Thanks

                                  1 Reply Last reply
                                  0
                                  • sierdzioS Offline
                                    sierdzioS Offline
                                    sierdzio
                                    Moderators
                                    wrote on last edited by
                                    #21

                                    I'm afraid some custom x and y setting is the way to go. You could try anchoring, but it would be too rigid.

                                    (Z(:^

                                    1 Reply Last reply
                                    0
                                    • Z Offline
                                      Z Offline
                                      Zaxy
                                      wrote on last edited by
                                      #22

                                      yes, I think so as well, I will add posX, posY as roles in my model, in the Repeater will have something like x: posX, y: posY ... and use the paint function to draw a line.

                                      thanks

                                      1 Reply Last reply
                                      0
                                      • Z Offline
                                        Z Offline
                                        Zaxy
                                        wrote on last edited by
                                        #23

                                        just one question: when is the paint() function called ? Always, when a change on the Node object has been done ?

                                        1 Reply Last reply
                                        0
                                        • Z Offline
                                          Z Offline
                                          Zaxy
                                          wrote on last edited by
                                          #24

                                          I implemented the paint() function of Node in the following way:

                                          @void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
                                          {
                                          QPen pen;
                                          pen.setColor(Qt::blue);
                                          pen.setStyle(Qt::SolidLine);
                                          pen.setWidth(2);
                                          painter->setPen(pen);
                                          painter->setRenderHints(QPainter::Antialiasing, true);

                                          for (QList<Node*>::const_iterator itParent = _parents.constBegin();
                                               itParent != _parents.constEnd();
                                               itParent++)
                                          {
                                              QPoint startPoint(this->posX(), this->posY());
                                              QPoint endPoint((*itParent)->posX(), (*itParent)->posY());
                                          
                                              painter->drawLine(startPoint, endPoint);
                                          }
                                          

                                          }@

                                          Than in the main.cpp I create 3 Nodes, and two of them as connected (Node3 has as parent Node2). But I don't see the line in the DeclarativeView window.

                                          Do I need to emit a signal that the line should be painted or how could I call the paint function explicitly ? I'd like to know how does it work and when is it called this paint function ?

                                          Thanks in advance

                                          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