[PyQt] selecting a bezier curve

Tom Brown nextstate at gmail.com
Sun Apr 14 02:06:33 BST 2013


I've found that this problem isn't specific to a bezier curve. If I change
the curve to a straight line, I observe the same problem. So, I would think
that it has something to do with the way I'm setting up the view.

Any ideas would be appreciated.

Thanks!
Tom


On Sat, Apr 13, 2013 at 5:15 PM, Tom Brown <nextstate at gmail.com> wrote:

> I've created a simple application (see below) that draws a bezier curve. I
> want to give the user the ability to select the curve so they can move it
> around. However, I'm having trouble selecting the curve in an intuitive
> fashion. When I click on the curve, the point I click on is actually far
> away from the curve.
>
> For example, when I click on the left end of the curve, the x-coordinate
> of the point where I clicked is about 100 pixels away from the x-coordinate
> of the point of the curve I clicked on.
>
> The code below demonstrates this problem.
>
> Any ideas why this is happening or what I'm doing wrong?
>
> Thanks!
> Tom
>
> <code>
> from math import sqrt
> from sys import argv
>
> from PyQt4.Qt import QApplication
> from PyQt4.QtCore import QPointF, Qt
> from PyQt4.QtGui import (
>     QColor,
>     QGraphicsItem,
>     QGraphicsView,
>     QGraphicsScene,
>     QPainterPath,
> )
>
>
> class View(QGraphicsView):
>     def __init__(self, parent=None):
>         super(View, self).__init__(parent)
>         self.epsilon = 11.0
>         self.graphics_scene = QGraphicsScene(self)
>         self.setScene(self.graphics_scene)
>         self.add_curve()
>
>     def mousePressEvent(self, event):
>         if event.button() == Qt.LeftButton:
>             self.select_item_at(event.x(), event.y())
>
>     def select_item_at(self, x, y):
>         self.unselect_items()
>         for item in self.items():
>             if item.contains_point(x, y, self.epsilon):
>                 item.set_selected(True)
>                 item.update()
>
>     def unselect_items(self):
>         for item in self.items():
>             item.set_selected(False)
>             item.update()
>
>     def add_curve(self):
>         color = QColor(255, 0, 0)
>         x0 = 600.0
>         y0 = 400.0
>         x1 = 800.0
>         y1 = 500.0
>         x2 = 1000.0
>         y2 = 500.0
>         x3 = 1200.0
>         y3 = 400.0
>         control_points = (QPointF(x0, y0), QPointF(x1, y1),
>             QPointF(x2, y2), QPointF(x3, y3))
>         curve = Curve(color, control_points)
>         self.graphics_scene.addItem(curve)
>
>
> class Curve(QGraphicsItem):
>     def __init__(self, color, control_points, parent=None, scene=None):
>         super(Curve, self).__init__(parent, scene)
>         self.selected = False
>         self.color = color
>         self.path = QPainterPath()
>         self.path.moveTo(control_points[0])
>         self.path.cubicTo(*control_points[1:])
>
>     def set_selected(self, selected):
>         self.selected = selected
>
>     def contains_point(self, x, y, epsilon):
>         p = (x, y)
>         min_distance = float(0x7fffffff)
>         t = 0.0
>         while t < 1.0:
>             point = self.path.pointAtPercent(t)
>             spline_point = (point.x(), point.y())
>             print p, spline_point
>             distance = self.distance(p, spline_point)
>             if distance < min_distance:
>                 min_distance = distance
>             t += 0.1
>         print min_distance, epsilon
>         return (min_distance <= epsilon)
>
>     def boundingRect(self):
>         return self.path.boundingRect()
>
>     def paint(self, painter, option, widget):
>         painter.setPen(self.color)
>         painter.setBrush(self.color)
>         painter.strokePath(self.path, painter.pen())
>
>     def distance(self, p0, p1):
>         a = p1[0] - p0[0]
>         b = p1[1] - p0[1]
>         return sqrt(a * a + b * b)
>
>
> if __name__ == '__main__':
>     app = QApplication(argv)
>     view = View()
>     view.setGeometry(100, 100, 1600, 900)
>     view.setWindowTitle('MainWindow')
>     view.show()
>     app.exec_()
>
> </code>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20130413/8499c837/attachment.html>


More information about the PyQt mailing list