I have a list of points. For example, `points = [[160, 75], [115, 567]]`.

How to draw a line in PyQt4, so it would be something like this:

EDIT: For the record, I'm trying to implement Bezier Curves, so it looked like this:

Here is the code I have at the moment:

``from PyQt4.QtGui import QWidget, QPolygonF, QPainter, QPen, QBrush, QColor, \QApplication, QIcon, QVBoxLayout, QSlider, QHBoxLayout, QPushButton, QLCDNumberfrom PyQt4.QtCore import QObject, SIGNAL, SLOT, QPointF, Qt, QRectF, QPointFimport time, sys#================================================================# For the next block I used this post# http://stackoverflow.com/a/3220819/736306,# but I wish to replace it with self.liniar_bez(),# biliniar_bez(), self.cubic_bez() and self.fourG_bez()# because I want to control 't' with self.sliderdef avg(a, b):xa, ya = axb, yb = breturn (xa + xb) * 0.5, (ya + yb) * 0.5def bez4split(p0, p1, p2, p3, p4):p01 = avg(p0, p1)p12 = avg(p1, p2)p23 = avg(p2, p3)p34 = avg(p3, p4)p012 = avg(p01, p12)p123 = avg(p12, p23)p234 = avg(p23, p34)p0123 = avg(p012, p123)p1234 = avg(p123, p234)p01234 = avg(p0123, p1234)return [(p0, p01, p012, p0123, p01234),(p01234, p1234, p234, p34, p4)]def bez4(p0, p1, p2, p3, p4, levels=5):if levels <= 0:return [p0, p4]else:(a0, a1, a2, a3, a4), (b0, b1, b2, b3, b4) = bez4split(p0, p1, p2, p3, p4)return (bez4(a0, a1, a2, a3, a4, levels - 1) +bez4(b0, b1, b2, b3, b4, levels - 1)[1:])#================================================================points = [[160, 75], [115, 567], [292, 58], [685, 194], [734, 517]]coords = bez4(*points)class Bezier(QWidget):def __init__(self, parent=None):QWidget.__init__(self, parent)self.lcd = QLCDNumber(self)self.slider = QSlider(Qt.Horizontal, self)self.slider.setRange(0, 100)self.closeButton = QPushButton('Close')bottomLayout = QHBoxLayout()bottomLayout.addWidget(self.lcd)bottomLayout.addWidget(self.slider)bottomLayout.addWidget(self.closeButton)mainLayout = QVBoxLayout()mainLayout.addStretch(1)mainLayout.addLayout(bottomLayout)self.setLayout(mainLayout)self.time = 0self.time_step = 0.025self.timer_id = self.startTimer(1)self.tracking = NoneQObject.connect(self.closeButton, SIGNAL('clicked(bool)'), app.exit)QObject.connect(self.slider, SIGNAL('valueChanged(int)'), self.lcd, SLOT('display(float)'))#self.slider.valueChanged.connect(self.lcd.display)self.setWindowTitle('Bonus Example')def poly(self, pts):return QPolygonF(map(lambda p: QPointF(*p), pts))def bezAnimation(self):painter = QPainter(self)painter.setRenderHints(QPainter.Antialiasing)pts = points[:]crds = coords[:]painter.setPen(QPen(QColor(Qt.lightGray), 3, Qt.DashDotDotLine))painter.drawPolyline(self.poly(pts))painter.setBrush(QBrush(QColor(255, 025, 0)))painter.setPen(QPen(QColor(Qt.lightGray), 1))for x, y in pts:painter.drawEllipse(QRectF(x - 4, y - 4, 8, 8))def paintEvent(self, event):self.bezAnimation()# As you know, 0.00 > 't' > 1.00# and QSlider does not provide support for float numbers,# so we simply divide t by 100def liniar_bez(self, p, t):t = t / 100.0new_p[0] = (1 - t) * p[0][0] + t * p[1][0]new_p[1] = (1 - t) * p[0][1] + t * p[1][1]def biliniar_bez(self, p, t):t = t / 100.0new_p[0][0] = ((1 - t) ** 2) * p[0][0] + 2 * (1 - t) * t * p[1][0] + (t ** 2) * p[2][0]new_p[0][1] = ((1 - t) ** 2) * p[0][1] + 2 * (1 - t) * t * p[1][1] + (t ** 2) * p[2][1]def cubic_bez(self, p, t):t = t / 100.0new_p[0][0] = ((1 - t) ** 3) * p[0][0] + 3 * ((1 - t) ** 2) * t * p[1][0] + (t ** 2) * p[2][0] + (t ** 3) * p[3][0]new_p[0][1] = ((1 - t) ** 3) * p[0][1] + 3 * ((1 - t) ** 2) * t * p[1][1] + (t ** 2) * p[2][1] + (t ** 3) * p[3][1]def fourG_bez(self, p, t):t = t / 100.0new_p[0][0] = ((1 - t) ** 4) * p[0][0] + 4 * ((1 - t) ** 3) * t * p[1][0] + 4 * (1 - t) * (t ** 2) * p[2][0] + 4 * (1 - t) * (t ** 3) * p[3][0] + (t ** 4) * p[4][0]new_p[0][1] = ((1 - t) ** 4) * p[0][1] + 4 * ((1 - t) ** 3) * t * p[1][1] + 4 * (1 - t) * (t ** 2) * p[2][1] + 4 * (1 - t) * (t ** 3) * p[3][1] + (t ** 4) * p[4][1]def timerEvent(self, event):if self.timer_id == event.timerId():#self.bezAnimation()self.time += self.time_stepself.update()def closeEvent(self, event):self.deleteLater()#================================================================# And this one too# http://stackoverflow.com/a/3220819/736306def mousePressEvent(self, event):i = min(range(len(points)),key=lambda i: (event.x() - points[i][0]) ** 2 +(event.y() - points[i][1]) ** 2)self.tracking = lambda p: points.__setitem__(i, p)def mouseMoveEvent(self, event):if self.tracking:self.tracking((event.x(), event.y()))self.update()def mouseReleaseEvent(self, event):self.tracking = None#================================================================if __name__ == '__main__':app = QApplication(sys.argv)form = Bezier()form.setGeometry(10, 30, 871, 727)form.show()sys.exit(app.exec_())``

So, my idea about how to solve this problem:

1. Buid all curves with self.biliniar_bez(),..., self.fourG_bez()

2. They share the same points, so they'll actually match in this points.

3. Move points (I think, that their position must match with t, so if t=0.25 then every point must pass at this time quarter of their lines)

The problem is in the way of moving points. I have coordinates of first and second point of every line. Need middle ones.

Refer the below code in your paint event to draw a line in Qt.

``````def paintEvent(self, event):
painter = Qt.QPainter()
painter.begin(self)
painter.pen().setWidth(int width)
painter.setPen(Qt.QColor(100,100,100))
painter.drawLine(x1,y1,x2,y2)
painter.end()
Qt.QFrame.paintEvent(self, event)
``````
1. If you are using normal widgets then you would be looking at QPainter.drawPath()
2. If you are using QGraphics, then you would be looking at QGraphicsPathItem

Either of these two would have similar approaches where during your draw you would have to build the line incrementally over time. Review your own previous question for a specific example of how to draw a line over time: Make an animated wave with drawPolyline in PySide/PyQt

As an example, if you were using QGraphics, then you would have a QGraphicsPathItem instance in your scene. Then you would animate it by looping and updating QPainterPath by incrementally setting the complete path: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qpainterpath.html#cubicTo

Top