[PyQt] selecting a bezier curve

Christophe BAL projetmbc at gmail.com
Sun Apr 14 02:52:02 BST 2013


Hello,
can you give your solution ?

Christophe.


2013/4/14 Tom Brown <nextstate at gmail.com>

> 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>
>>>
>>
>>
>
> _______________________________________________
> PyQt mailing list    PyQt at riverbankcomputing.com
> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20130414/c5adc3a0/attachment.html>


More information about the PyQt mailing list