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 <nextst...@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@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt