[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