[Qt-interest] FW: Qt object initialisation list problem
Andy Bolsover
andybolsover at yahoo.co.uk
Sun Nov 21 00:00:58 CET 2010
Thanks to John McClurkin and particularly K. Frank for pointing me back to
the debugger. I can at last see what's happening.
Each of the calls to function Controller::setPos() triggers a call to
Controller::itemChange() which in turn calls Bezier's updateCurve(). This
alters the m_pA, m_pB etc before these can be used to initialise the
Controller positions.
The net result is that only the first Controller is positioned correctly,
the other are located at (0,0).
My take-away lesson is that the test for QGraphicsItem::ItemPositionChange
can succeed after calling setPos(), not only a mouse move. Obvious, but I
didn't see it.
Thanks for the assistance
Andy
> -----Original Message-----
> From: qt-interest-bounces at trolltech.com [mailto:qt-interest-
> bounces at trolltech.com] On Behalf Of K. Frank
> Sent: 19 November 2010 16:06
> To: Qt-interest
> Subject: Re: [Qt-interest] Qt object initialisation list problem
>
> Hi John and Andy -
>
> I don't understand what's going wrong here or how to fix it, but
> I think that the comment about creating the QPointF's on the heap
> is a red herring.
>
> On Fri, Nov 19, 2010 at 7:31 AM, John McClurkin <jwm at nei.nih.gov> wrote:
> > Andy Bolsover wrote:
> >> I have a small test program to draw a Bezier curve with 2 end points
> and
> >> ...
> >>
> >> Bezier *bez = new Bezier(QPointF(0,100), QPointF(0,0),
> >> QPointF(100,0), QPointF(100,100));
> >> ...
> >
> > 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);
>
> I don't see how this can matter (unless there is some c++ nuance
> I'm missing).
>
> >From below, the Bezier constructor is call by value, so it should
> neither know nor care whether the QPointF's passed in are local
> temporary variables on the stack, or dereferenced values of pointers
> pointing to QPoiutF's on the heap. (In the latter case, you
> presumably have a small memory leak, unless you delete the
> QPointF's in some other piece of code.)
>
> In either case, QPointF's should be copy-constructed into the
> private QPointF member variables when the constructor is called
> (and the local temporary variables are still valid at this point in time).
>
> > ...
> >>
> >> 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.
>
> This seems odd. The setPos() member function of your Controller
> takes its QPointF's as const references, so it shouldn't be able
> to change them.
>
> >> 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?
>
> Unfortunately not.
>
> >>
> >> Here is the code for the Bezier and its Controller objects.
> >>
> >> class Controller : public QGraphicsEllipseItem {
> >> ...
> >>
> >> class Bezier : public QGraphicsItem {
> >>
> >> public:
> >>
> >> Bezier(QPointF pA, QPointF pB, QPointF cA, QPointF cB,
> >> QGraphicsItem *parent = 0, QGraphicsScene *scene = 0);
>
> Bezier gets its QPointF's by value.
>
> >> ...
> >>
> >> 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) {
>
> The QPointF's are copy-constructed into the member variables.
>
> >> ...
> >> // The following initialisation method does not work
> >>
> >> // m_pA, m_pB, m_cA, and m_cB are all initialised wrongly
> (0,0)
>
> Just to check, are m_pA, et al., initialized wrongly, i.e., at the time of
> their initialization in the Bezier's constructor's initializer list?
>
> Or do they start out with the correct values, but then end up with bad
> values, after calling setPos(m_pA) etc.?
>
> >>
> >> // 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);
> >> */
>
> setPos takes a const ref: setPos ( const QPointF & )
>
> So it shouldn't be changing the value of m_pA, etc.
>
> >>
> >> // 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);
> >> }
>
> This is quite odd. I don't see anything wrong with what you are doing.
>
> The only thing I can think of at this point would be to poke around
> with the debugger and try to find out where the m_pA, et al. are
> getting set to the bad values (0, 0).
>
> Or, if you can whittle it down to a minimal, self-contained example
> program that displays the bug, I (we?) might be able to take a look
> at it.
>
> >> ...
>
> Good luck.
>
>
> K. Frank
>
> _______________________________________________
> Qt-interest mailing list
> Qt-interest at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-interest
More information about the Qt-interest-old
mailing list