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. Need some advice: how to draw a line between two objects.
Forum Updated to NodeBB v4.3 + New Features

Need some advice: how to draw a line between two objects.

Scheduled Pinned Locked Moved QML and Qt Quick
15 Posts 6 Posters 11.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.
  • E Offline
    E Offline
    excalibur1491
    wrote on last edited by
    #5

    Ok thank you, I already thought about that, but it seamed to me a bit "too much" for just drawing a line ^^. But I think that is what I will do (I have already done that for the two "rectangles" that I want to attach, which are no rectangles in fact)

    In that case, my class Line should be something like this?:
    @
    class A : public QDeclarativeItem{ /plenty of code/ };

    class Line : public QDeclarativeItem{
    private:
    A* _attachPoint1;
    A* _attachPoint2;
    public:
    Line(A* pt1 = NULL, A* pt2 = NULL);
    public slots:
    void attachTo(A* pt1, A* pt2);
    void changePosition(A* newPosition);
    };
    @

    and then I have to connect:
    @
    connect(_attachPoint1,signal(onPositionChanged(A*)),this,SLOT(changePosition(A*)))

    void changePosition(A* newPosition){
    //Then I change my Line object properties thanks to the coordenates from the passed A object.
    }
    @

    But there is no onPositionChanged signal in my class A ... How can I code it?
    The position of my A objects changes when it is dragged (setting drag.target in a MouseArea into my object in QML), so, how can connect the fact of being dragged to my Line object?
    @
    A {
    id: myObject
    color: "red"
    width: 100
    height: 100
    MouseArea{
    id: ma;
    anchors.fill : parent;
    drag.target: myObject
    }
    }
    @
    I mean, when I drag it, the x and y properties of the object change, but how can I catch that changing?

    thank you again!

    1 Reply Last reply
    0
    • shavS Offline
      shavS Offline
      shav
      wrote on last edited by
      #6

      [quote author="excalibur1491" date="1357123707"]
      But there is no onPositionChanged signal in my class A … How can I code it?
      The position of my A objects changes when it is dragged (setting drag.target in a MouseArea into my object in QML), so, how can connect the fact of being dragged to my Line object?
      [/quote]

      If I understand you correctly you want to catch when your component is moving, right? If so, you may connect two signals to your slots, for example:
      @
      connect(item, SIGNAL(xChanged()), SLOT(onXChanged()));
      connect(item, SIGNAL(yChanged()), SLOT(onYChanged()));
      @

      In both methods which you set as slot you may get a sender objects and get his X and Y positions. The code for that may looks like:
      @

      void QmlApplicationViewer::onXChanged()
      {
      QDeclarativeItem* item = sender();

      if(item != NULL)
      {
          qDebug()<<"x: "<<item->x();
      }
      

      }

      void QmlApplicationViewer::onYChanged()
      {
      QDeclarativeItem* item = sender();

      if(item != NULL)
      {
          qDebug()<<"y: "<<item->y();
      }
      

      }
      @

      I hope this will help you.

      Mac OS and iOS Developer

      1 Reply Last reply
      0
      • E Offline
        E Offline
        excalibur1491
        wrote on last edited by
        #7

        Hi!

        Thanks you a lot! I didn't knew about "sender()" and that "connect".
        Ok, so I see more or less how to do the Line object and the two slots.
        But I dont really see how to emit those signals because when my object is moved, I'm not even sure that the object itself notices since it's moved with a drag in a MouseArea inside the object. So the object won't emit those signals.
        The big difficulty I have is how to emit those signals.
        The only way I see is:
        @
        A{
        id: a
        MouseArea{
        drag.target: a
        onPositionChanged:{
        if (drag.active){
        emit a.onXChanged()
        emit a.onYChanged()
        }
        }
        }
        }
        @

        Is that ven possible?
        There must be a better way to do it, isn't it?

        Thank you again, you're all being of big help :)

        1 Reply Last reply
        0
        • shavS Offline
          shavS Offline
          shav
          wrote on last edited by
          #8

          The signals xChanged() and yChanged() is a standard signals for QDeclarativeItem objects. So, If your component is a subclass from QDeclarativeItem you can use it like:
          @
          A{
          id: a

          onXChanged: {
          //Some code here
          }
          onYChanged: {
          //Some code here
          }
          }
          @

          If you need to get information about new position inside QML object. If you need get this information in C++ class which you want to use this signals, you can connect to the signal to some slot insdie you C++ class.

          If you want to send a some signal you may use something like this:
          @
          //<id_of_component>.<signal_name>(<list_of_parameters>);
          a.onXChanged(a.x);
          @

          By the way, when you try to set a new position for object with id like 'a' the signal 'onXChanged' will called automatically for current object. So you don't needed call this signal manually.

          Mac OS and iOS Developer

          1 Reply Last reply
          0
          • E Offline
            E Offline
            excalibur1491
            wrote on last edited by
            #9

            Thank you a lot!
            I didn't knew those signals were standard. When I read the documntation of QDeclarativeItem I was looking for somethink like "onPoistionChanged" and I forgot that signals don't appear in the methods list. My bad.

            Any way, thank you a lot to all of you. I will try to do that then.

            1 Reply Last reply
            0
            • U Offline
              U Offline
              utcenter
              wrote on last edited by
              #10

              [quote author="Jens" date="1357046647"]... Note that this works through rasterization so you will loose hardware acceleration and might have significantly higher memory requirements as a tradeoff. [/quote]

              Doesn't this use OpenGL accelerated QPainter, which IIRC draws paths by triangulating and drawing hardware accelerated geometry?

              On a side note, I myself have done a "mindmap network" style of app and think it will be significantly easier to implement with the trusty old QGraphicsView/Item/scene stack than with QML. Performance was pretty good too.

              1 Reply Last reply
              0
              • E Offline
                E Offline
                excalibur1491
                wrote on last edited by
                #11

                Hi again, I have started coding and it works mor or less, but I have a problem that I don't undestand at all:
                I have a line between two rectangles, and when I move them the line moves. The problem is that when I move one of them, the line moves properly, but when I move the other the line becomes "dashed", and ugly... it does not move properlly, and I don't get why since it only happens on one side.

                Here is the code:
                here is the base qml, nothing special abut it:
                @
                import QtQuick 1.0

                Rectangle{
                color: "white"
                width: 500
                height: 500

                Rectangle{
                objectName: "rec1"
                id: rec1
                x: 10
                y: 10
                width: 100
                height: 100
                radius: 50;
                color: "red"
                MouseArea{
                id:marec1
                anchors.fill: parent
                drag.target: rec1
                }
                }

                Rectangle{
                objectName: "rec2"
                id: rec2
                x: 200
                y: 200
                width: 100
                height: 100
                radius: 50;
                color: "blue"

                 MouseArea{
                    id:marec2
                 anchors.fill: parent
                 drag.target: rec2
                 }     
                

                }
                }
                @

                Now, the Line class:
                @

                #include <QDeclarativeItem>
                #include <QPainter>
                #include <QPen>
                #include <QColor>

                class Line: public QDeclarativeItem{

                Q_OBJECT

                private:
                QDeclarativeItem* pt1;
                QDeclarativeItem* pt2;

                public:
                Line(QDeclarativeItem* pt1 = NULL, QDeclarativeItem* pt2 = NULL);

                public slots:
                void attachPt1(QDeclarativeItem* pt1);
                void attachPt2(QDeclarativeItem* pt2);
                void paint(QPainter* p, const QStyleOptionGraphicsItem* o = NULL, QWidget* w= NULL);
                void _update(); //The aim of this slot is that update() is not a slot, so it only calls update().
                };
                @

                The implementation:
                @
                #include "Line.h"
                #include <QTextStream>
                #include <QIODevice>

                Line::Line(QDeclarativeItem* pt1, QDeclarativeItem* pt2):QDeclarativeItem(NULL),pt1(pt1),pt2(pt2){
                setFlag(QGraphicsItem::ItemHasNoContents, false);
                }

                void Line::attachPt1(QDeclarativeItem* pt1){
                this->pt1 = pt1;
                update();
                QObject::connect(pt1,SIGNAL(xChanged()),this,SLOT(_update()));
                QObject::connect(pt1,SIGNAL(yChanged()),this,SLOT(_update()));
                }
                void Line::attachPt2(QDeclarativeItem* pt2){
                this->pt2 = pt2;
                update();
                QObject::connect(pt2,SIGNAL(xChanged()),this,SLOT(_update()));
                QObject::connect(pt2,SIGNAL(yChanged()),this,SLOT(_update()));
                }
                void Line::_update(){update();}

                void Line::paint(QPainter* p, const QStyleOptionGraphicsItem* o, QWidget* w){

                QTextStream ts (stderr,QIODevice::WriteOnly);
                ts << "paint " << pt1<< " " << pt2 << " " <<sender()<< endl;
                QPen pen(QColor("red"),2);
                p->setPen(pen);
                QLine line(pt1->x()+pt1->width()/2,
                pt1->y()+pt1->height()/2,
                pt2->x()+pt2->width()/2,
                pt2->y()+pt2->height()/2);
                p->drawLine(line);

                }
                @
                When the two extremities are set, the connection is done.
                The drawing function only uses a QLine, nothing special about it.

                Last, the main:
                @
                #include <QApplication>
                #include <QDebug>
                #include <QObject>
                #include <QDeclarativeEngine>
                #include <QDeclarativeComponent>
                #include <QDeclarativeItem>
                #include <QDeclarativeView>
                #include <QString>
                #include <QTextStream>
                #include <QIODevice>

                #include "Line.h"

                int main(int argc, char* argv[]){

                QApplication app(argc, argv);
                QTextStream ts(stderr,QIODevice::WriteOnly);

                qmlRegisterType<Line>("LinesTest", 1,0, "Line");

                QDeclarativeView* view = new QDeclarativeView;
                view->setSource(QUrl::fromLocalFile("Base.qml";);

                QDeclarativeEngine* e = view->engine();
                QDeclarativeComponent c (e,QUrl("example.qml"));
                Line *l = qobject_cast<Line *>(c.create());

                qWarning() << c.errors();

                QDeclarativeItem* r1 = view->rootObject()->findChild<QDeclarativeItem*>("rec1");
                QDeclarativeItem* r2 = view->rootObject()->findChild<QDeclarativeItem*>("rec2");

                l->attachPt1(r1);
                l->attachPt2(r2);

                l->setParentItem(qobject_cast<QDeclarativeItem*>(view->rootObject()));
                view->show();

                return app.exec();
                }
                @
                The example.qml file does not contain anythin special, just this:
                @
                import LinesTest 1.0
                import QtQuick 1.0

                Line{
                smooth: true
                //color: "red";
                }
                @

                There is nt big code, but I really dont see where the bug comes from. It is the first time I use a QLine class, I hope it is OK.

                Thank you again!

                1 Reply Last reply
                0
                • E Offline
                  E Offline
                  excalibur1491
                  wrote on last edited by
                  #12

                  Any idea, please?

                  thanks again

                  1 Reply Last reply
                  0
                  • j1eloJ Offline
                    j1eloJ Offline
                    j1elo
                    wrote on last edited by
                    #13

                    I didn't review your code at detail but lately I've been doing the same as you (a graph editor) and, while in my case I wanted to find a pure QML+JavaScript solution with Qt 5, I found a Line component example from Nokia, implemented in Qt 4. Maybe you should follow their code:
                    http://www.developer.nokia.com/Community/Wiki/Creating_a_custom_QML_element_with_Qt

                    1 Reply Last reply
                    0
                    • U Offline
                      U Offline
                      utcenter
                      wrote on last edited by
                      #14

                      For taking advantage of the scenegrapgh, you might want to look at this example, which pretty much implements a geometry node for a bezier curve:

                      http://doc-snapshot.qt-project.org/5.0/qtqml/quick-scenegraph-customgeometry.html

                      1 Reply Last reply
                      0
                      • E Offline
                        E Offline
                        excalibur1491
                        wrote on last edited by
                        #15

                        Hi, I have already ued this example: http://www.developer.nokia.com/Community/Wiki/Creating_a_custom_QML_element_with_Qt
                        and it works great.
                        I thought about the Beziers curve, but I need to have a mousearea covering the line so it would be way more dificult.
                        Any way, thank you all

                        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