[Qt-interest] Qt object initialisation list problem
John McClurkin
jwm at nei.nih.gov
Fri Nov 19 13:31:05 CET 2010
Andy Bolsover wrote:
> I have a small test program to draw a Bezier curve with 2 end points and
> 2 control points (Controller objects). The Controller objects can be
> dragged by the mouse to change the shape of the Bezier curve. I have a
> QGraphicsScene and QGraphicsView - the Bezier curve is drawn using code
> as follows
>
>
>
> Bezier *bez = new Bezier(QPointF(0,100), QPointF(0,0),
> QPointF(100,0), QPointF(100,100));
>
> scene->addItem(bez);
>
> bez->setPos(0, 0);
>
> bez->updateCurve();
>
My guess would be that you are constructing new QPointF objects in the
call to Bezier. Try constructing the QPointF first, then passing them in.
QPointF *a = new QPointF(0,100);
QPointF *b = new QPointF(0,0);
QPointF *c = new QPointF(100,0);
QPointF *d = new QPointF(100,100);
Bezier *bez = new Bezier(*a, *b, *c, *d);
>
>
> The Bezier constructor receives four QPointF which are stored in private
> variables.
>
> These QPointF are also used to initialise the locations of the four
> Controller objects
>
> If I use the passed-in QPointF directly to set positions of the
> Controller objects everything is ok,
>
> But if I use the private variables to set positions of the Controller
> objects the initial locations are wrong and the private variables are
> also altered.
>
> As a result the Bezier curve is the wrong shape when first drawn
>
>
>
> I have been looking at this for long enough without seeing what is going
> wrong.
>
> I thought it was a C++ problem at first – not Qt, but the problem goes
> away when I simplify the test program by removing the Qt
>
> Any suggestions on what I have done wrong?
>
>
>
> Here is the code for the Bezier and its Controller objects.
>
>
>
> class Controller : public QGraphicsEllipseItem {
>
> public:
>
> Controller(Bezier *bezier);
>
> private:
>
> Bezier *m_bezier;
>
> QVariant itemChange(GraphicsItemChange change, const
> QVariant &value);
>
> };
>
>
>
> class Bezier : public QGraphicsItem {
>
> public:
>
> Bezier(QPointF pA, QPointF pB, QPointF cA, QPointF cB,
> QGraphicsItem *parent = 0, QGraphicsScene *scene = 0);
>
> QRectF boundingRect() const;
>
> QPainterPath shape() const;
>
> void paint(QPainter *painter, const QStyleOptionGraphicsItem
> *option, QWidget *widget = 0);
>
> Controller *endA;
>
> Controller *endB;
>
> Controller *controlA;
>
> Controller *controlB;
>
> void updateCurve();
>
>
>
> private:
>
> QPointF m_pA;
>
> QPointF m_pB;
>
> QPointF m_cA;
>
> QPointF m_cB;
>
> };
>
>
>
>
>
> Bezier::Bezier(QPointF pA, QPointF pB, QPointF cA, QPointF cB,
> QGraphicsItem *parent, QGraphicsScene *scene)
>
> : QGraphicsItem(parent, scene), m_pA(pA),
> m_pB(pB), m_cA(cA), m_cB(cB) {
>
>
>
> endA = new Controller(this); // constructs
> a mouse-moveable 'hot spot' for end A of bezier curve
>
> endB = new Controller(this); // constructs
> a mouse-moveable 'hot spot' for end B of bezier curve
>
> controlA = new Controller(this); // constructs a
> mouse-moveable 'hot spot' for endA control point
>
> controlB = new Controller(this); // constructs a
> mouse-moveable 'hot spot' for endB control point
>
>
>
> // The following initialisation method does not work
>
> // m_pA, m_pB, m_cA, and m_cB are all initialised wrongly (0,0)
>
> // endA position is initialised correctly, but the other
> Controllers are wrongly located at 0, 0
>
>
>
> /* endA->setPos(m_pA);
>
> endB->setPos(m_pB);
>
> controlA->setPos(m_cA);
>
> controlB->setPos(m_cB);
>
> */
>
>
>
> // The following initialisation method works OK
>
> // m_pA, m_pB, m_cA, and m_cB are all initialised ok
>
> // endA, endB, controlA & controlB are all positioned OK
>
>
>
> endA->setPos(pA);
>
> endB->setPos(pB);
>
> controlA->setPos(cA);
>
> controlB->setPos(cB);
>
> }
>
>
>
> QRectF Bezier::boundingRect() const {
>
> return shape().controlPointRect().normalized();
>
> }
>
>
>
> QPainterPath Bezier::shape() const {
>
> QPainterPath bezpath;
>
> bezpath.moveTo(m_pA);
>
> bezpath.cubicTo(m_cA, m_cB, m_pB);
>
> return bezpath;
>
> }
>
>
>
> void Bezier::updateCurve() { // initiate redrawing of
> bezier based on new location of Controller objects
>
> prepareGeometryChange();
>
> m_pA = endA->pos();
>
> m_pB = endB->pos();
>
> m_cA = controlA->pos();
>
> m_cB = controlB->pos();
>
> }
>
>
>
> void Bezier::paint(QPainter *painter, const QStyleOptionGraphicsItem
> *option, QWidget *widget) {
>
> painter->drawPath(shape());
>
> }
>
>
>
> Controller::Controller(Bezier *bezier) : QGraphicsEllipseItem() {
>
> setFlag(QGraphicsItem::ItemIsMovable, true);
>
> setFlag(QGraphicsItem::ItemIsSelectable, true);
>
> setRect(-5, -5, 10, 10);
>
> setParentItem(bezier);
>
> m_bezier = bezier;
>
> }
>
>
>
> QVariant Controller::itemChange(GraphicsItemChange change, const
> QVariant &value) {
>
> if (change == QGraphicsItem::ItemPositionChange) {
>
> m_bezier->updateCurve();
>
> }
>
> return value;
>
> }
>
>
>
>
>
More information about the Qt-interest-old
mailing list