<div dir="ltr"><div><div><span style="font-family:courier new,monospace">Sure! My solution is below.<br><br></span></div><span style="font-family:courier new,monospace"><code><br>from math import sqrt<br>from sys import argv<br>
<br>from PyQt4.Qt import QApplication<br>from PyQt4.QtCore import QPoint, QPointF, Qt<br>from PyQt4.QtGui import (<br>    QColor,<br>    QGraphicsItem,<br>    QGraphicsView,<br>    QGraphicsScene,<br>    QPainterPath,<br>
)<br><br><br>class View(QGraphicsView):<br>    def __init__(self, parent=None):<br>        super(View, self).__init__(parent)<br>        self.epsilon = 11.0<br>        self.graphics_scene = QGraphicsScene(self)<br>        self.setScene(self.graphics_scene)<br>
        self.add_curve()<br><br>    def mousePressEvent(self, event):<br>        if event.button() == Qt.LeftButton:<br>            self.select_item_at(event.x(), event.y())<br><br>    def select_item_at(self, x, y):<br>        point = self.mapToScene(QPoint(x, y))<br>
        self.unselect_items()<br>        for item in self.items():<br>            if item.contains_point(point.x(), point.y(), self.epsilon):<br>                item.set_selected(True)<br>                item.update()<br>
<br>    def unselect_items(self):<br>        for item in self.items():<br>            item.set_selected(False)<br>            item.update()<br><br>    def add_curve(self):<br>        color = QColor(255, 0, 0)<br>        x0 = 600.0<br>
        y0 = 400.0<br>        x1 = 800.0<br>        y1 = 500.0<br>        x2 = 1000.0<br>        y2 = 500.0<br>        x3 = 1200.0<br>        y3 = 400.0<br>        control_points = (QPointF(x0, y0), QPointF(x1, y1),<br>            QPointF(x2, y2), QPointF(x3, y3))<br>
        curve = Curve(color, control_points)<br>        self.graphics_scene.addItem(curve)<br><br><br>class Curve(QGraphicsItem):<br>    def __init__(self, color, control_points, parent=None, scene=None):<br>        super(Curve, self).__init__(parent, scene)<br>
        self.selected = False<br>        self.color = color<br>        self.path = QPainterPath()<br>        self.path.moveTo(control_points[0])<br>        self.path.cubicTo(*control_points[1:])<br><br>    def set_selected(self, selected):<br>
        self.selected = selected<br><br>    def contains_point(self, x, y, epsilon):<br>        p = (x, y)<br>        min_distance = float(0x7fffffff)<br>        t = 0.0<br>        while t < 1.0:<br>            point = self.path.pointAtPercent(t)<br>
            spline_point = (point.x(), point.y())<br>            print p, spline_point<br>            distance = self.distance(p, spline_point)<br>            if distance < min_distance:<br>                min_distance = distance<br>
            t += 0.1<br>        print min_distance, epsilon<br>        return (min_distance <= epsilon)<br><br>    def boundingRect(self):<br>        return self.path.boundingRect()<br><br>    def paint(self, painter, option, widget):<br>
        painter.setPen(self.color)<br>        painter.setBrush(self.color)<br>        painter.strokePath(self.path, painter.pen())<br><br>    def distance(self, p0, p1):<br>        a = p1[0] - p0[0]<br>        b = p1[1] - p0[1]<br>
        return sqrt(a * a + b * b)<br><br><br>if __name__ == '__main__':<br>    app = QApplication(argv)<br>    view = View()<br>    view.setGeometry(100, 100, 1600, 900)<br>    view.setWindowTitle('MainWindow')<br>
    view.show()<br>    app.exec_()<br><br></span></div><span style="font-family:courier new,monospace"></code><br></span></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Apr 13, 2013 at 6:52 PM, Christophe BAL <span dir="ltr"><<a href="mailto:projetmbc@gmail.com" target="_blank">projetmbc@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hello,<div>can you give your solution ?</div><div><br></div><div>Christophe.</div></div><div class="gmail_extra">
<br><br><div class="gmail_quote">2013/4/14 Tom Brown <span dir="ltr"><<a href="mailto:nextstate@gmail.com" target="_blank">nextstate@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><div dir="ltr"><div>Ah! I found the QGraphicsView.mapToScene() method. This solved my problem.<br>
<br></div>Thanks!<span><font color="#888888"><br>
Tom<br></font></span></div><div><div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Apr 13, 2013 at 6:06 PM, Tom Brown <span dir="ltr"><<a href="mailto:nextstate@gmail.com" target="_blank">nextstate@gmail.com</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>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.<br>



<br></div>Any ideas would be appreciated.<br><br></div>Thanks!<span><font color="#888888"><br>Tom</font></span><div><div><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Apr 13, 2013 at 5:15 PM, Tom Brown <span dir="ltr"><<a href="mailto:nextstate@gmail.com" target="_blank">nextstate@gmail.com</a>></span> wrote:<br>



<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><span style="font-family:courier new,monospace">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.<br>




<br></span></div><span style="font-family:courier new,monospace">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.<br>




<br></span></div><div><span style="font-family:courier new,monospace">The code below demonstrates this problem.<br><br></span></div><div><span style="font-family:courier new,monospace">Any ideas why this is happening or what I'm doing wrong?<br>




<br></span></div><div><span style="font-family:courier new,monospace">Thanks!<br>Tom<br></span></div><div><span style="font-family:courier new,monospace"><br></span></div><span style="font-family:courier new,monospace"><code><br>




from math import sqrt<br>from sys import argv<br><br>from PyQt4.Qt import QApplication<br>from PyQt4.QtCore import QPointF, Qt<br>from PyQt4.QtGui import (<br>    QColor,<br>    QGraphicsItem,<br>    QGraphicsView,<br>    QGraphicsScene,<br>




    QPainterPath,<br>)<br><br><br>class View(QGraphicsView):<br>    def __init__(self, parent=None):<br>        super(View, self).__init__(parent)<br>        self.epsilon = 11.0<br>        self.graphics_scene = QGraphicsScene(self)<br>




        self.setScene(self.graphics_scene)<br>        self.add_curve()<br><br>    def mousePressEvent(self, event):<br>        if event.button() == Qt.LeftButton:<br>            self.select_item_at(event.x(), event.y())<br>




<br>    def select_item_at(self, x, y):<br>        self.unselect_items()<br>        for item in self.items():<br>            if item.contains_point(x, y, self.epsilon):<br>                item.set_selected(True)<br>                item.update()<br>




<br>    def unselect_items(self):<br>        for item in self.items():<br>            item.set_selected(False)<br>            item.update()<br><br>    def add_curve(self):<br>        color = QColor(255, 0, 0)<br>        x0 = 600.0<br>




        y0 = 400.0<br>        x1 = 800.0<br>        y1 = 500.0<br>        x2 = 1000.0<br>        y2 = 500.0<br>        x3 = 1200.0<br>        y3 = 400.0<br>        control_points = (QPointF(x0, y0), QPointF(x1, y1),<br>            QPointF(x2, y2), QPointF(x3, y3))<br>




        curve = Curve(color, control_points)<br>        self.graphics_scene.addItem(curve)<br><br><br>class Curve(QGraphicsItem):<br>    def __init__(self, color, control_points, parent=None, scene=None):<br>        super(Curve, self).__init__(parent, scene)<br>




        self.selected = False<br>        self.color = color<br>        self.path = QPainterPath()<br>        self.path.moveTo(control_points[0])<br>        self.path.cubicTo(*control_points[1:])<br><br>    def set_selected(self, selected):<br>




        self.selected = selected<br><br>    def contains_point(self, x, y, epsilon):<br>        p = (x, y)<br>        min_distance = float(0x7fffffff)<br>        t = 0.0<br>        while t < 1.0:<br>            point = self.path.pointAtPercent(t)<br>




            spline_point = (point.x(), point.y())<br>            print p, spline_point<br>            distance = self.distance(p, spline_point)<br>            if distance < min_distance:<br>                min_distance = distance<br>




            t += 0.1<br>        print min_distance, epsilon<br>        return (min_distance <= epsilon)<br><br>    def boundingRect(self):<br>        return self.path.boundingRect()<br><br>    def paint(self, painter, option, widget):<br>




        painter.setPen(self.color)<br>        painter.setBrush(self.color)<br>        painter.strokePath(self.path, painter.pen())<br><br>    def distance(self, p0, p1):<br>        a = p1[0] - p0[0]<br>        b = p1[1] - p0[1]<br>




        return sqrt(a * a + b * b)<br><br><br>if __name__ == '__main__':<br>    app = QApplication(argv)<br>    view = View()<br>    view.setGeometry(100, 100, 1600, 900)<br>    view.setWindowTitle('MainWindow')<br>




    view.show()<br>    app.exec_()<br><br></span></div><span style="font-family:courier new,monospace"></code></span><br></div>
</blockquote></div><br></div></div></div></div>
</blockquote></div><br></div>
</div></div><br></div></div>_______________________________________________<br>
PyQt mailing list    <a href="mailto:PyQt@riverbankcomputing.com" target="_blank">PyQt@riverbankcomputing.com</a><br>
<a href="http://www.riverbankcomputing.com/mailman/listinfo/pyqt" target="_blank">http://www.riverbankcomputing.com/mailman/listinfo/pyqt</a><br></blockquote></div><br></div>
</blockquote></div><br></div>