[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