[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