airglide
17th February 2013, 18:55
Hello everyone,
I've tried to create an ArrowItem (derived from QGraphicsItem) which displays an Arrow.
#include "arrowitem.h"
ArrowItem::ArrowItem(QGraphicsItem *parent)
:QGraphicsItem(parent)
{
}
void ArrowItem::changeLine(QPointF start, QPointF end)
{
double rSquared = 25.0;
//Point which lies on line which indicates begining of the Arrow
// ---|>
QPointF onLine = 19.0/20.0*(end-start)+start;
double m = (end.y()-start.y())/(end.x()-start.x());
double mRect = -1/m;
double b = onLine.y()- mRect*onLine.x();
double c = qPow(mRect,2)+1.0;
double d = 2.0*b*mRect -2.0*onLine.x() -2.0*mRect*onLine.y();
double e = qPow(b,2) + qPow(onLine.x(),2) + qPow(onLine.y(),2) -2.0*b*onLine.y() -rSquared;
double xOne = (-d + qSqrt(d*d-4.0*c*e))/(2.0*c);
double yOne = xOne*mRect + b;
double xTwo = (-d - qSqrt(d*d-4.0*c*e))/(2.0*c);
double yTwo = xTwo*mRect + b;
QPointF pointOne = QPointF(xOne,yOne);
QPointF pointTwo = QPointF(xTwo,yTwo);
triangle << pointOne << pointTwo << end << pointOne;
line.setPoints(start, end);
double distanceX;
double width;
double distanceY;
double height;
double left;
double top;
if(start.x() < end.x())
{
if(pointOne.x() > pointTwo.x())
{
distanceX = pointOne.x();
}else{
distanceX = pointOne.x();
}
if(end.x() > distanceX)
{
distanceX = end.x();
}
width = distanceX - start.x();
left = start.x();
}else{
if(start.x() == end.x())
{
width = 20.0;
}else{
if(pointOne.x() < pointTwo.x())
{
distanceX = pointOne.x();
}else{
distanceX = pointOne.x();
}
if(end.x() < distanceX)
{
distanceX = end.x();
}
width = start.x() - distanceX;
left = distanceX;
}
}
//get height
if(start.y() > end.y())
{
if(pointOne.y() < pointTwo.y())
{
distanceY = pointOne.y();
}else{
distanceY = pointTwo.y();
if(end.y() < distanceY)
{
distanceY = end.y();
}
}
height = start.y() - distanceY;
top = start.y();
}else{
if(start.y() == end.y())
{
height = 20.0;
}else{
if(pointOne.y() > pointTwo.y())
{
distanceY = pointOne.y();
}else{
distanceY = pointTwo.y();
if(end.y() > distanceY)
{
distanceY = end.y();
}
}
height = distanceY - start.y();
top = distanceY;
}
}
double penwidth = 3.0;
prepareGeometryChange();
rect = QRectF(left -penwidth/2,top -penwidth/2,width + penwidth,height + penwidth);
update();
}
QRectF ArrowItem::boundingRect() const
{
return rect;
}
void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
painter->setPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin));
painter->drawLine(line);
//painter->setBrush(QBrush(Qt::black));
painter->drawPolygon(triangle);
}
I don't really get where I've made a mistake because I used the prepareGeometrychange() method before I change the boundingRect and I've called the update() method
If I create a new object of this class and call the method ArrowItem::changeLine with the starting Point (where the mousePressEvent happened) and end point (where the mousemoveEvent happened), there are pieces left on the screen.
thank you very much
airglide
I've tried to create an ArrowItem (derived from QGraphicsItem) which displays an Arrow.
#include "arrowitem.h"
ArrowItem::ArrowItem(QGraphicsItem *parent)
:QGraphicsItem(parent)
{
}
void ArrowItem::changeLine(QPointF start, QPointF end)
{
double rSquared = 25.0;
//Point which lies on line which indicates begining of the Arrow
// ---|>
QPointF onLine = 19.0/20.0*(end-start)+start;
double m = (end.y()-start.y())/(end.x()-start.x());
double mRect = -1/m;
double b = onLine.y()- mRect*onLine.x();
double c = qPow(mRect,2)+1.0;
double d = 2.0*b*mRect -2.0*onLine.x() -2.0*mRect*onLine.y();
double e = qPow(b,2) + qPow(onLine.x(),2) + qPow(onLine.y(),2) -2.0*b*onLine.y() -rSquared;
double xOne = (-d + qSqrt(d*d-4.0*c*e))/(2.0*c);
double yOne = xOne*mRect + b;
double xTwo = (-d - qSqrt(d*d-4.0*c*e))/(2.0*c);
double yTwo = xTwo*mRect + b;
QPointF pointOne = QPointF(xOne,yOne);
QPointF pointTwo = QPointF(xTwo,yTwo);
triangle << pointOne << pointTwo << end << pointOne;
line.setPoints(start, end);
double distanceX;
double width;
double distanceY;
double height;
double left;
double top;
if(start.x() < end.x())
{
if(pointOne.x() > pointTwo.x())
{
distanceX = pointOne.x();
}else{
distanceX = pointOne.x();
}
if(end.x() > distanceX)
{
distanceX = end.x();
}
width = distanceX - start.x();
left = start.x();
}else{
if(start.x() == end.x())
{
width = 20.0;
}else{
if(pointOne.x() < pointTwo.x())
{
distanceX = pointOne.x();
}else{
distanceX = pointOne.x();
}
if(end.x() < distanceX)
{
distanceX = end.x();
}
width = start.x() - distanceX;
left = distanceX;
}
}
//get height
if(start.y() > end.y())
{
if(pointOne.y() < pointTwo.y())
{
distanceY = pointOne.y();
}else{
distanceY = pointTwo.y();
if(end.y() < distanceY)
{
distanceY = end.y();
}
}
height = start.y() - distanceY;
top = start.y();
}else{
if(start.y() == end.y())
{
height = 20.0;
}else{
if(pointOne.y() > pointTwo.y())
{
distanceY = pointOne.y();
}else{
distanceY = pointTwo.y();
if(end.y() > distanceY)
{
distanceY = end.y();
}
}
height = distanceY - start.y();
top = distanceY;
}
}
double penwidth = 3.0;
prepareGeometryChange();
rect = QRectF(left -penwidth/2,top -penwidth/2,width + penwidth,height + penwidth);
update();
}
QRectF ArrowItem::boundingRect() const
{
return rect;
}
void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
painter->setPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin));
painter->drawLine(line);
//painter->setBrush(QBrush(Qt::black));
painter->drawPolygon(triangle);
}
I don't really get where I've made a mistake because I used the prepareGeometrychange() method before I change the boundingRect and I've called the update() method
If I create a new object of this class and call the method ArrowItem::changeLine with the starting Point (where the mousePressEvent happened) and end point (where the mousemoveEvent happened), there are pieces left on the screen.
thank you very much
airglide