[PyQt] selecting a bezier curve

Tom Brown nextstate at gmail.com
Sun Apr 14 02:20:00 BST 2013


Ah! I found the QGraphicsView.mapToScene() method. This solved my problem.

Thanks!
Tom


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

> 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/c2d29fb9/attachment-0001.html>


More information about the PyQt mailing list