1

I created a QGraphicsPathItem by passing the constructor a QPainterPath with about 10 QPoint's in it. Now how can I move the points in the path around?

For example:

This to create a box:

path = QtGui.QPainterPath()
path.moveTo(0, 0)
path.lineTo(10, 0)
path.lineTo(10, 10)
path.lineTo(0, 10)

line = QtGui.QGraphicsPathItem()
line.setPath(path)

Now after some time goes by I want to make this box wider by grabbing the top & bottom right points and moving them right. How can I access the points? The Qt documentation for QPainterPath indicates that path.elementAt(i) is the way to access data within the path, but that returns a QElementObject and I could not find much documentation for an "element object", and it is definitely not a QPointF (which is what I would expect to get...right?). So how can I get a QPointF out of this element? And once I do get the points, is it fine to just call their QPointF.setX() and QPointF.setY() and the line will re-draw, or do I need to re-set it to the QGraphicsPathItem with a new call to line.setPath()?

As a note this is PyQt4, python 2.7. However I'll take a C++ answer if you have it, though I don't know C++ at all it seems pretty easy to translate.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Spencer
  • 1,931
  • 1
  • 21
  • 44

1 Answers1

2

you can get the coordinates through path.elementAt(i).x, path.elementAt(i).y, and set new values ​​using the path.setElementPositionAt() method.

In the next section I show an example.

import sys

import random

from PyQt4 import QtGui, QtCore

def movePoints():
    p = line.path()
    for i in range(p.elementCount()):
        xo, yo = p.elementAt(i).x, p.elementAt(i).y
        xn, yn = (e+10*(random.random()-0.5) for e in  (xo, yo))
        p.setElementPositionAt(i, xn, yn)
    line.setPath(p)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    w = QtGui.QGraphicsView()
    scene = QtGui.QGraphicsScene(w)
    w.setScene(scene)
    timer = QtCore.QTimer()
    timer.timeout.connect(movePoints)

    path = QtGui.QPainterPath()
    path.moveTo(0, 0)
    path.lineTo(10, 0)
    path.lineTo(10, 10)
    path.lineTo(0, 10)

    line = QtGui.QGraphicsPathItem()
    line.setPath(path)
    scene.addItem(line)
    timer.start(1000)
    w.show()
    sys.exit(app.exec_())

If you want to use QPointF , the code equivalent to the example is the following:

def movePoints():
    p = line.path()
    for i in range(p.elementCount()):
        point = QtCore.QPointF(p.elementAt(i))
        point += QtCore.QPointF(10*random.random()-5, 10*random.random()-5)
        p.setElementPositionAt(i, point.x(), point.y())
    line.setPath(p)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks, this is just what I needed! I'm able to use p.setElementPositionAt() for my needs. Can you point me to a good learning resource for "casting" in python? This is the first I've heard of it. – Spencer Apr 14 '18 at 05:06
  • @Spencer Read http://doc.qt.io/archives/qt-4.8/qpainterpath-element.html#operator-QPointF – eyllanesc Apr 14 '18 at 05:25
  • Interesting, I didn't realize you could do casting that way. I guess I just assumed you could only cast with the built in python methods(str, int, float, etc). – Spencer Apr 14 '18 at 05:29
  • @Spencer In c ++ you can create operators, I think that in Python what you are doing is adding one more constructor to QPointF – eyllanesc Apr 14 '18 at 05:31
  • Yeah now that I look at it you're right. Sorry I was a little tired last night... It's not doing a c++ "cast" per se, it's just creating a new QPointF with the element as a constructor. Thanks for the help! – Spencer Apr 15 '18 at 02:11