xd123
10th April 2020, 22:20
I have used this code to implement resizing in my QGraphicsRectItem and QGraphicsEllipseItem, since both Rect and Ellipse have implemented function SetRect(qreal x, qreal y, qreal width, qreal height) it was not a problem, but with QGraphicsPolygonItem the nearest function is setPolygon() but it only takes a QPolygonf& Polygon as parameter which doesn't work with my code of sizeGripItem
mainwindow.cpp
class RectResizer : public SizeGripItem::Resizer // resize class for rectagle
{
public:
virtual void operator()(QGraphicsItem* item, const QRectF& rect)
{
QGraphicsRectItem* rectItem =
dynamic_cast<QGraphicsRectItem*>(item);
if (rectItem)
{
rectItem->setRect(rect);
}
}
};
class EllipseResizer : public SizeGripItem::Resizer //resize class for ellipse
{
public:
virtual void operator()(QGraphicsItem* item, const QRectF& rect)
{
QGraphicsEllipseItem* ellipseItem =
dynamic_cast<QGraphicsEllipseItem*>(item);
if (ellipseItem)
{
ellipseItem->setRect(rect);
}
}
};
class PolygonResizer : public SizeGripItem::Resizer // resize class for polygon
{
public:
virtual void operator()(QGraphicsItem* item, const QRectF& rect)
{
QGraphicsPolygonItem* polygonItem =
dynamic_cast<QGraphicsPolygonItem*>(item);
if (polygonItem)
{
polygonItem->setPolygon(rect);
} //^ doesn't work when i attempt to resize shape, it changes to rectangle
}
};
sizegripitem.cpp
#include "sizegripitem.h"
#include <QBrush>
SizeGripItem::HandleItem::HandleItem(int positionFlags, SizeGripItem* parent)
: QGraphicsRectItem(-4, -4, 8, 8, parent),
positionFlags_(positionFlags),
parent_(parent)
{
setBrush(QBrush(Qt::lightGray));
setFlag(ItemIsMovable);
setFlag(ItemSendsGeometryChanges);
}
int SizeGripItem::HandleItem::positionFlags() const
{
return positionFlags_;
}
QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemC hange change,
const QVariant &value)
{
QVariant retVal = value;
if (change == ItemPositionChange)
{
retVal = restrictPosition(value.toPointF());
}
else if (change == ItemPositionHasChanged)
{
QPointF pos = value.toPointF();
switch (positionFlags_)
{
case TopLeft:
parent_->setTopLeft(pos);
break;
case Top:
parent_->setTop(pos.y());
break;
case TopRight:
parent_->setTopRight(pos);
break;
case Right:
parent_->setRight(pos.x());
break;
case BottomRight:
parent_->setBottomRight(pos);
break;
case Bottom:
parent_->setBottom(pos.y());
break;
case BottomLeft:
parent_->setBottomLeft(pos);
break;
case Left:
parent_->setLeft(pos.x());
break;
}
}
return retVal;
}
QPointF SizeGripItem::HandleItem::restrictPosition(const QPointF& newPos)
{
QPointF retVal = pos();
if (positionFlags_ & Top || positionFlags_ & Bottom)
retVal.setY(newPos.y());
if (positionFlags_ & Left || positionFlags_ & Right)
retVal.setX(newPos.x());
if (positionFlags_ & Top && retVal.y() > parent_->rect_.bottom())
retVal.setY(parent_->rect_.bottom());
else if (positionFlags_ & Bottom && retVal.y() < parent_->rect_.top())
retVal.setY(parent_->rect_.top());
if (positionFlags_ & Left && retVal.x() > parent_->rect_.right())
retVal.setX(parent_->rect_.right());
else if (positionFlags_ & Right && retVal.x() < parent_->rect_.left())
retVal.setX(parent_->rect_.left());
return retVal;
}
SizeGripItem::SizeGripItem(Resizer* resizer, QGraphicsItem* parent)
: QGraphicsItem(parent),
resizer_(resizer)
{
if (parentItem())
rect_ = parentItem()->boundingRect();
handleItems_.append(new HandleItem(TopLeft, this));
handleItems_.append(new HandleItem(Top, this));
handleItems_.append(new HandleItem(TopRight, this));
handleItems_.append(new HandleItem(Right, this));
handleItems_.append(new HandleItem(BottomRight, this));
handleItems_.append(new HandleItem(Bottom, this));
handleItems_.append(new HandleItem(BottomLeft, this));
handleItems_.append(new HandleItem(Left, this));
updateHandleItemPositions();
}
SizeGripItem::~SizeGripItem()
{
if (resizer_)
delete resizer_;
}
QRectF SizeGripItem::boundingRect() const
{
return rect_;
}
void SizeGripItem::paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget)
{
}
#define IMPL_SET_FN(TYPE, POS) \
void SizeGripItem::set ## POS (TYPE v) \
{ \
rect_.set ## POS (v); \
doResize(); \
}
IMPL_SET_FN(qreal, Top)
IMPL_SET_FN(qreal, Right)
IMPL_SET_FN(qreal, Bottom)
IMPL_SET_FN(qreal, Left)
IMPL_SET_FN(const QPointF&, TopLeft)
IMPL_SET_FN(const QPointF&, TopRight)
IMPL_SET_FN(const QPointF&, BottomRight)
IMPL_SET_FN(const QPointF&, BottomLeft)
void SizeGripItem::doResize()
{
if (resizer_)
{
(*resizer_)(parentItem(), rect_);
updateHandleItemPositions();
}
}
void SizeGripItem::updateHandleItemPositions()
{
foreach (HandleItem* item, handleItems_)
{
item->setFlag(ItemSendsGeometryChanges, false);
switch (item->positionFlags())
{
case TopLeft:
item->setPos(rect_.topLeft());
break;
case Top:
item->setPos(rect_.left() + rect_.width() / 2 - 1,
rect_.top());
break;
case TopRight:
item->setPos(rect_.topRight());
break;
case Right:
item->setPos(rect_.right(),
rect_.top() + rect_.height() / 2 - 1);
break;
case BottomRight:
item->setPos(rect_.bottomRight());
break;
case Bottom:
item->setPos(rect_.left() + rect_.width() / 2 - 1,
rect_.bottom());
break;
case BottomLeft:
item->setPos(rect_.bottomLeft());
break;
case Left:
item->setPos(rect_.left(),
rect_.top() + rect_.height() / 2 - 1);
break;
}
item->setFlag(ItemSendsGeometryChanges, true);
}
}
sizegripitem.h
#ifndef SIZEGRIPITEM_H
#define SIZEGRIPITEM_H
#include <QGraphicsItem>
#include <QGraphicsRectItem>
class SizeGripItem : public QGraphicsItem
{
private:
enum
{
Top = 0x1,
Bottom = 0x2,
Left = 0x4,
TopLeft = Top | Left,
BottomLeft = Bottom | Left,
Right = 0x8,
TopRight = Top | Right,
BottomRight = Bottom | Right
};
class HandleItem : public QGraphicsRectItem
{
public:
HandleItem(int positionFlags, SizeGripItem* parent);
int positionFlags() const;
protected:
virtual QVariant itemChange(GraphicsItemChange change,
const QVariant &value);
private:
QPointF restrictPosition(const QPointF& newPos);
int positionFlags_;
SizeGripItem* parent_;
};
public:
class Resizer
{
public:
virtual void operator()(QGraphicsItem* item,
const QRectF& rect) = 0;
};
SizeGripItem(Resizer* resizer = 0, QGraphicsItem* parent = 0);
virtual ~SizeGripItem();
virtual QRectF boundingRect() const;
virtual void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget = 0);
void setTopLeft(const QPointF& pos);
void setTop(qreal y);
void setTopRight(const QPointF& pos);
void setRight(qreal x);
void setBottomRight(const QPointF& pos);
void setBottom(qreal y);
void setBottomLeft(const QPointF& pos);
void setLeft(qreal x);
private:
void doResize();
void updateHandleItemPositions();
QList<HandleItem*> handleItems_;
QRectF rect_;
Resizer* resizer_;
};
#endif // SIZEGRIPITEM_H
I can't really think of a way to resize a polygon since the library misses on a lot of functions Rect and Ellipse do have implemented. Thanks for any help or suggestions on how to proceed with resizing a polygon item
mainwindow.cpp
class RectResizer : public SizeGripItem::Resizer // resize class for rectagle
{
public:
virtual void operator()(QGraphicsItem* item, const QRectF& rect)
{
QGraphicsRectItem* rectItem =
dynamic_cast<QGraphicsRectItem*>(item);
if (rectItem)
{
rectItem->setRect(rect);
}
}
};
class EllipseResizer : public SizeGripItem::Resizer //resize class for ellipse
{
public:
virtual void operator()(QGraphicsItem* item, const QRectF& rect)
{
QGraphicsEllipseItem* ellipseItem =
dynamic_cast<QGraphicsEllipseItem*>(item);
if (ellipseItem)
{
ellipseItem->setRect(rect);
}
}
};
class PolygonResizer : public SizeGripItem::Resizer // resize class for polygon
{
public:
virtual void operator()(QGraphicsItem* item, const QRectF& rect)
{
QGraphicsPolygonItem* polygonItem =
dynamic_cast<QGraphicsPolygonItem*>(item);
if (polygonItem)
{
polygonItem->setPolygon(rect);
} //^ doesn't work when i attempt to resize shape, it changes to rectangle
}
};
sizegripitem.cpp
#include "sizegripitem.h"
#include <QBrush>
SizeGripItem::HandleItem::HandleItem(int positionFlags, SizeGripItem* parent)
: QGraphicsRectItem(-4, -4, 8, 8, parent),
positionFlags_(positionFlags),
parent_(parent)
{
setBrush(QBrush(Qt::lightGray));
setFlag(ItemIsMovable);
setFlag(ItemSendsGeometryChanges);
}
int SizeGripItem::HandleItem::positionFlags() const
{
return positionFlags_;
}
QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemC hange change,
const QVariant &value)
{
QVariant retVal = value;
if (change == ItemPositionChange)
{
retVal = restrictPosition(value.toPointF());
}
else if (change == ItemPositionHasChanged)
{
QPointF pos = value.toPointF();
switch (positionFlags_)
{
case TopLeft:
parent_->setTopLeft(pos);
break;
case Top:
parent_->setTop(pos.y());
break;
case TopRight:
parent_->setTopRight(pos);
break;
case Right:
parent_->setRight(pos.x());
break;
case BottomRight:
parent_->setBottomRight(pos);
break;
case Bottom:
parent_->setBottom(pos.y());
break;
case BottomLeft:
parent_->setBottomLeft(pos);
break;
case Left:
parent_->setLeft(pos.x());
break;
}
}
return retVal;
}
QPointF SizeGripItem::HandleItem::restrictPosition(const QPointF& newPos)
{
QPointF retVal = pos();
if (positionFlags_ & Top || positionFlags_ & Bottom)
retVal.setY(newPos.y());
if (positionFlags_ & Left || positionFlags_ & Right)
retVal.setX(newPos.x());
if (positionFlags_ & Top && retVal.y() > parent_->rect_.bottom())
retVal.setY(parent_->rect_.bottom());
else if (positionFlags_ & Bottom && retVal.y() < parent_->rect_.top())
retVal.setY(parent_->rect_.top());
if (positionFlags_ & Left && retVal.x() > parent_->rect_.right())
retVal.setX(parent_->rect_.right());
else if (positionFlags_ & Right && retVal.x() < parent_->rect_.left())
retVal.setX(parent_->rect_.left());
return retVal;
}
SizeGripItem::SizeGripItem(Resizer* resizer, QGraphicsItem* parent)
: QGraphicsItem(parent),
resizer_(resizer)
{
if (parentItem())
rect_ = parentItem()->boundingRect();
handleItems_.append(new HandleItem(TopLeft, this));
handleItems_.append(new HandleItem(Top, this));
handleItems_.append(new HandleItem(TopRight, this));
handleItems_.append(new HandleItem(Right, this));
handleItems_.append(new HandleItem(BottomRight, this));
handleItems_.append(new HandleItem(Bottom, this));
handleItems_.append(new HandleItem(BottomLeft, this));
handleItems_.append(new HandleItem(Left, this));
updateHandleItemPositions();
}
SizeGripItem::~SizeGripItem()
{
if (resizer_)
delete resizer_;
}
QRectF SizeGripItem::boundingRect() const
{
return rect_;
}
void SizeGripItem::paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget)
{
}
#define IMPL_SET_FN(TYPE, POS) \
void SizeGripItem::set ## POS (TYPE v) \
{ \
rect_.set ## POS (v); \
doResize(); \
}
IMPL_SET_FN(qreal, Top)
IMPL_SET_FN(qreal, Right)
IMPL_SET_FN(qreal, Bottom)
IMPL_SET_FN(qreal, Left)
IMPL_SET_FN(const QPointF&, TopLeft)
IMPL_SET_FN(const QPointF&, TopRight)
IMPL_SET_FN(const QPointF&, BottomRight)
IMPL_SET_FN(const QPointF&, BottomLeft)
void SizeGripItem::doResize()
{
if (resizer_)
{
(*resizer_)(parentItem(), rect_);
updateHandleItemPositions();
}
}
void SizeGripItem::updateHandleItemPositions()
{
foreach (HandleItem* item, handleItems_)
{
item->setFlag(ItemSendsGeometryChanges, false);
switch (item->positionFlags())
{
case TopLeft:
item->setPos(rect_.topLeft());
break;
case Top:
item->setPos(rect_.left() + rect_.width() / 2 - 1,
rect_.top());
break;
case TopRight:
item->setPos(rect_.topRight());
break;
case Right:
item->setPos(rect_.right(),
rect_.top() + rect_.height() / 2 - 1);
break;
case BottomRight:
item->setPos(rect_.bottomRight());
break;
case Bottom:
item->setPos(rect_.left() + rect_.width() / 2 - 1,
rect_.bottom());
break;
case BottomLeft:
item->setPos(rect_.bottomLeft());
break;
case Left:
item->setPos(rect_.left(),
rect_.top() + rect_.height() / 2 - 1);
break;
}
item->setFlag(ItemSendsGeometryChanges, true);
}
}
sizegripitem.h
#ifndef SIZEGRIPITEM_H
#define SIZEGRIPITEM_H
#include <QGraphicsItem>
#include <QGraphicsRectItem>
class SizeGripItem : public QGraphicsItem
{
private:
enum
{
Top = 0x1,
Bottom = 0x2,
Left = 0x4,
TopLeft = Top | Left,
BottomLeft = Bottom | Left,
Right = 0x8,
TopRight = Top | Right,
BottomRight = Bottom | Right
};
class HandleItem : public QGraphicsRectItem
{
public:
HandleItem(int positionFlags, SizeGripItem* parent);
int positionFlags() const;
protected:
virtual QVariant itemChange(GraphicsItemChange change,
const QVariant &value);
private:
QPointF restrictPosition(const QPointF& newPos);
int positionFlags_;
SizeGripItem* parent_;
};
public:
class Resizer
{
public:
virtual void operator()(QGraphicsItem* item,
const QRectF& rect) = 0;
};
SizeGripItem(Resizer* resizer = 0, QGraphicsItem* parent = 0);
virtual ~SizeGripItem();
virtual QRectF boundingRect() const;
virtual void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget = 0);
void setTopLeft(const QPointF& pos);
void setTop(qreal y);
void setTopRight(const QPointF& pos);
void setRight(qreal x);
void setBottomRight(const QPointF& pos);
void setBottom(qreal y);
void setBottomLeft(const QPointF& pos);
void setLeft(qreal x);
private:
void doResize();
void updateHandleItemPositions();
QList<HandleItem*> handleItems_;
QRectF rect_;
Resizer* resizer_;
};
#endif // SIZEGRIPITEM_H
I can't really think of a way to resize a polygon since the library misses on a lot of functions Rect and Ellipse do have implemented. Thanks for any help or suggestions on how to proceed with resizing a polygon item