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. How to draw Bezier curves in QML?
QtWS25 Last Chance

How to draw Bezier curves in QML?

Scheduled Pinned Locked Moved QML and Qt Quick
16 Posts 8 Posters 17.1k 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.
  • F Offline
    F Offline
    Fenix Voltres
    wrote on last edited by
    #1

    Hello,
    I need to draw Bezier (preferably, or at least other cubic) curves in QML, is it possible? And if yes, how?
    I'm experienced with Qt C++, but I just have started discovering QML possibilities.

    This far I tried with QML's Pathview (AFAIK can't be displayed directly) and port of HTML5 canvas (which's really great, but I need whole area to be scalable, and since canvas is just a bitmap I'm not interested in it), but to no avail.

    I can draw curves directly in C++, but I need them to dynamically move (each curve is connecting two boxes which can be d&d) - it seems a bit tricky, is there an easier option to achieve this?

    When temptation brings me to my knees
    And I lay here drained of strength
    Show me kindness
    Show me beauty
    Show me truth

    1 Reply Last reply
    0
    • frankcyblogic.deF Offline
      frankcyblogic.deF Offline
      frankcyblogic.de
      wrote on last edited by
      #2

      I was also looking into realising some connected shapes logic with QtQuick some time ago. With standard QtQuick 1.x components it is not possible for sure. I think you have to extend QML with your own components.

      See here: http://doc.troll.no/4.7/qml-extending.html
      and here: http://doc.troll.no/4.7/qml-extending-tutorial-index.html

      Good luck, and let me know if you get it working;)

      1 Reply Last reply
      0
      • M Offline
        M Offline
        moo1
        wrote on last edited by
        #3

        Can you just use SVG as a source for the Image element? You shouldn't need any extension.

        1 Reply Last reply
        0
        • F Offline
          F Offline
          Fenix Voltres
          wrote on last edited by
          #4

          [quote author="moo1" date="1301956183"]Can you just use SVG as a source for the Image element? You shouldn't need any extension.[/quote]

          I can't, because I need these lines to dynamically adjust their shapes while I'm moving boxes. :/

          When temptation brings me to my knees
          And I lay here drained of strength
          Show me kindness
          Show me beauty
          Show me truth

          1 Reply Last reply
          0
          • frankcyblogic.deF Offline
            frankcyblogic.deF Offline
            frankcyblogic.de
            wrote on last edited by
            #5

            Hmmm... in theory even a border image would do. Compute start and end point, derive angle, rotate the arrow image, etc. Of course the arrow head needs to be fully inside the border.

            1 Reply Last reply
            0
            • M Offline
              M Offline
              Merinas
              wrote on last edited by
              #6

              I've made an extension for myself, which allow me to draw line, with cubic option.
              You will need to create a qml plugin. And to something like that
              :
              @void Line::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
              {

              //setting drawing param
              painter->setRenderHint(QPainter::Antialiasing);
              painter->setPen(Qt::NoPen);

              // Construct the main path
              QPainterPath totalPath;
              totalPath.moveTo(m_points.at(0)->x(),m_points.at(0)->y());
              for (int i=1; i<m_points.size(); ++i)
              {
              totalPath.lineTo(m_points.at(i)->x(),m_points.at(i)->y());
              }

              //drawing directly
              painter->strokePath(totalPath, QPen(m_pencolor, m_penWidth));

              }@

              For adding cubic you could look at the "path stroking exampe":http://doc.qt.nokia.com/latest/demos-pathstroke.html

              And no you could not use an svg file because the svg is just render once at start.

              1 Reply Last reply
              0
              • F Offline
                F Offline
                Fenix Voltres
                wrote on last edited by
                #7

                Merinas,
                I've made similar thing as you and it works literally halfway - when I move one anchor point only the left and upper areas are updated.
                Doeas anyone have an idea how to fix it?

                Here is how it looks like:

                http://student.agh.edu.pl/~wmaciej/nodes.png

                my paint() fction:

                @void Line::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
                {
                QPainterPath path;

                painter->setRenderHint(QPainter::Antialiasing);
                painter->setPen(Qt::NoPen);
                
                QPointF middle1( (m_startingPoint.x() + m_endingPoint.x())/4, (m_startingPoint.y() + m_endingPoint.y())/2 );
                QPointF middle2( 3*(m_startingPoint.x() + m_endingPoint.x())/4, (m_startingPoint.y() + m_endingPoint.y())/2 );
                
                path.moveTo(m_startingPoint.x(), m_startingPoint.y());
                path.cubicTo( middle1.x(), middle1.y(),
                              middle2.x(), middle2.y(),
                              m_endingPoint.x(), m_endingPoint.y() );
                
                painter->strokePath( path, QPen(m_penColor, m_penWidth) );
                

                // painter->setPen( QPen(Qt::red) );
                // painter->drawRect( path.boundingRect().normalized() );
                }@

                Whole code can be found "here":http://student.agh.edu.pl/~wmaciej/LineTest.zip.

                When temptation brings me to my knees
                And I lay here drained of strength
                Show me kindness
                Show me beauty
                Show me truth

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  Merinas
                  wrote on last edited by
                  #8

                  Your right image is really strange... Oo Cubic was working fine for me since have use Qt example code so I can't really help you. Maybe you can build a gif showing your issue. This may help us to understand what goes wrong...

                  1 Reply Last reply
                  0
                  • F Offline
                    F Offline
                    Fenix Voltres
                    wrote on last edited by
                    #9

                    After some experiments I think it's general QML-related problem, not generated by my implementation.
                    But it's behavior is very strange:

                    If I connect starting and ending points of my curve to some points on two QML Rectangles it looks fine.
                    When I move the rectangles (with MouseArea's drag) Qt updates only the region from (window's) 0,0 to lower right point of moving rectangle, no matter where my line is pinned to. It means in the case the whole curve is placed above moving rect's lower right corner, everything updates as it should; otherwise (= when whole curve's bounding rect is not contained in mentioned area) only that part which's in is updated.

                    What's more, when my curve is displayed wrongly and the window needs to be repainted - i.e. I change it's size or click on other window to lose focus - curve * magically * updates correctly.

                    Explixitly calling QDeclarativeView object to update itself doesn't help.

                    Does anyone have the idea what can I do? It's really important for me to have cubic lines available from QML..

                    @_Merinas_:
                    Yeah, it's a bit hard to explain what my particular problem is, so besides my story here is a gif:

                    !http://student.agh.edu.pl/~wmaciej/QML-line.gif(my problem)!

                    Hope it's gonna help you understand what I mean.

                    When temptation brings me to my knees
                    And I lay here drained of strength
                    Show me kindness
                    Show me beauty
                    Show me truth

                    1 Reply Last reply
                    0
                    • R Offline
                      R Offline
                      rselva123
                      wrote on last edited by
                      #10

                      The line breaks in windows but I don't see any problem in Qt simulator. Works as expected - no broken line. So it's some bug in QML specific to windows.

                      1 Reply Last reply
                      0
                      • F Offline
                        F Offline
                        Fenix Voltres
                        wrote on last edited by
                        #11

                        In the beggining I thought you're talking about the OS, so I switched to Linux - but this error is also present there.

                        I found a brute-force workaround: automatically resize top window by 1px back and forth.
                        Pitiful and very CPU-eating, but works for now.

                        Shold I report this as a bug?

                        When temptation brings me to my knees
                        And I lay here drained of strength
                        Show me kindness
                        Show me beauty
                        Show me truth

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          andre
                          wrote on last edited by
                          #12

                          Yes, please report, but please add your (minimal) testcase to your bugreport and also link back and forth between this topic and the bug report.

                          1 Reply Last reply
                          0
                          • M Offline
                            M Offline
                            Merinas
                            wrote on last edited by
                            #13

                            When the point of the curve move, Haven't you forget to call the update function ?

                            1 Reply Last reply
                            0
                            • M Offline
                              M Offline
                              mbrasser
                              wrote on last edited by
                              #14

                              Hi,

                              Does setting QGraphicsView::FullViewportUpdate on the QDeclarativeView work?

                              Does your Line element set a width and height? This is needed by QDeclarativeItem's "boundingRect":http://doc.qt.nokia.com/4.7/qgraphicsitem.html#boundingRect implementation (which determines what area needs to be repainted when update() is called for the element).

                              Regards,
                              Michael

                              1 Reply Last reply
                              0
                              • F Offline
                                F Offline
                                Fenix Voltres
                                wrote on last edited by
                                #15

                                [quote author="Merinas" date="1302507353"]When the point of the curve move, Haven't you forget to call the update function ? [/quote]

                                No, I haven't forgot;

                                [quote author="mbrasser" date="1302567263"]Hi,

                                Does setting QGraphicsView::FullViewportUpdate on the QDeclarativeView work?

                                Does your Line element set a width and height? This is needed by QDeclarativeItem's "boundingRect":http://doc.qt.nokia.com/4.7/qgraphicsitem.html#boundingRect implementation (which determines what area needs to be repainted when update() is called for the element).

                                Regards,
                                Michael[/quote]

                                Setting QGraphicsView::FullViewportUpdate on QDeclarativeView works fine - it's still CPU-eating, but it better solution than mine previous;
                                I didn't implement boundingRect() method at all, nor I set width and height. After doing this it's a bit better - the rectangle in which my line is updated is bigger than previously, but it differs - sometimes whole line is updated, sometimes not.

                                Is there any particular order I should set new values in in paint() method? Now it looks like this:
                                @
                                void Line::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
                                {
                                painter->setRenderHint(QPainter::Antialiasing);
                                painter->setPen(Qt::NoPen);

                                QPointF middle1( (m_startingPoint.x() + m_endingPoint.x())/10, m_startingPoint.y() );
                                QPointF middle2( 9*(m_startingPoint.x() + m_endingPoint.x())/10, m_endingPoint.y() );
                                
                                QPainterPath path;
                                path.moveTo( m_startingPoint );
                                path.cubicTo( middle1, middle2, m_endingPoint );
                                
                                rect = path.boundingRect();
                                setHeight( rect.height() );
                                setWidth( rect.width() );
                                
                                painter->strokePath( path, QPen(m_penColor, m_penWidth) );
                                

                                // painter->setPen( QPen(Qt::red) );
                                // painter->drawRect( boundingRect() );
                                }

                                QRectF Line::boundingRect()
                                { return rect; }
                                @

                                Anyway - thank you, mbrasser, it's one step closer. :)

                                [EDIT:]

                                Testing goes on:

                                • Calling prepareGeometryChange(); inside a paint() method wasn't best idea. ;)

                                • As I see the problem is in these lines:

                                @ setHeight( rect.height() );
                                setWidth( rect.width() );@

                                When I set width and height properly bigger, it works. Just don't know the correct equation for these values to work in every case.

                                When temptation brings me to my knees
                                And I lay here drained of strength
                                Show me kindness
                                Show me beauty
                                Show me truth

                                1 Reply Last reply
                                0
                                • J Offline
                                  J Offline
                                  Jason.He
                                  wrote on last edited by
                                  #16

                                  @i think that is very easy to do .like below...just a simplest example!

                                  import QtQuick 1.0

                                  Rectangle {
                                  id: rect;
                                  width: 450;
                                  height:800;
                                  PathView {
                                  id: pathView;
                                  model: 300;
                                  delegate: Rectangle {
                                  id: dot;
                                  width: 1; height: 1;
                                  color: "black";
                                  }
                                  path: Path {
                                  startX: 20; startY: 0
                                  PathCubic {
                                  x: 180; y: 0
                                  control1X: -10; control1Y: 90
                                  control2X: 210; control2Y: 90
                                  }
                                  }
                                  }
                                  }

                                  another version! perfect result!

                                  import QtQuick 1.0

                                  Rectangle {
                                  id: rect;
                                  width: 450;
                                  height:800;
                                  PathView {
                                  id: conrPaV;
                                  anchors.fill: parent;
                                  model: 900;
                                  delegate: Rectangle {
                                  id: dot;
                                  width: 1; height: 1;
                                  color: "red";
                                  }

                                      path: Path {
                                          id: ph;
                                          startX: 0.0; startY: conrPaV.height/2.0;
                                          PathQuad {
                                              x: 40.0; y: conrPaV.height/2.0;
                                              controlX: 20.0; controlY: ph.startY -60.0;
                                          }
                                          PathQuad {
                                              x: 80.0; y: conrPaV.height/2.0;
                                              controlX: 60.0; controlY: ph.startY +60.0;
                                          }
                                      }
                                  }
                                  

                                  }

                                  @

                                  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