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.
  • 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