〇、先上效果图
一、QGraphicsItem自定义继承框架(如下图所示)
二、解释说明
- 代码中的 m_BlockItem 是 FlowBlockItem 类型,是成员变量;
- DotItem是边中点那个圆点
- TextItem是中间文本框
三、上代码
EnumHeader.h
#ifndef ENUMHEADER_H
#define ENUMHEADER_H
#include <QObject>
#include <QMetaEnum>
// Item的Class
#define ITEM_CLASS Qt::UserRole+1
// Item的相同Class中的不同分别
#define ITEM_TYPE Qt::UserRole+2
class EnumType : public QObject
{
Q_OBJECT
public:
// BlockItem的类别
enum BlockItemType
{
// 弧边矩形
BlockItemType_ArcRect = 1,
// 菱形
BlockItemType_Diamond,
// 矩形
BlockItemType_Rect,
// 平行四边形
BlockItemType_Parallelogram = 4
};
Q_ENUM(BlockItemType)
// BlockItem的SquareItem的所在方位
enum SquareItemDirection
{
SquareItem_LeftTop = 5,
SquareItem_LeftBottom,
SquareItem_RightBottom,
SquareItem_RightTop = 8
};
Q_ENUM(SquareItemDirection)
// BlockItem的DotItem的所在方位
enum DotItemDirection
{
DotItem_Left = 9,
DotItem_Bottom,
DotItem_Right,
DotItem_Top = 12
};
Q_ENUM(DotItemDirection)
enum LineItemDirection
{
LineItem_Left = 13,
LineItem_Down,
LineItem_Right,
LineItem_Up = 16
};
Q_ENUM(LineItemDirection)
// item的Class类
enum ItemClass
{
// UserType = 65536
ItemClass_FLowBlockItem = 65536 + 1,
ItemClass_FLowLineItem,
ItemClass_SquareItem,
ItemClass_DotItem,
ItemClass_TextItem,
ItemClass_QGraphicsPolygonItem
};
Q_ENUM(ItemClass)
};
#endif // ENUMHEADER_H
// 辅助方法(缩放模块单元)
void BlockItemClass::zoomBlockItem(SquareItem *squareItem, QPointF cursorPos)
{
// 鼠标点击的SquareItem所在的方位(枚举变量:squareItem在BlockItem四个角的方位标识)
int squareItemDirection;
// BlockItem的初始坐标
QPointF oldBlockPos;
// 缩放后模块新坐标点(因为除了通过左下角缩放,都会改变坐标,因为坐标是以左上角为基准的)
QPointF newBlockPos;
// 缩放时静止不动的点(举例:如果通过左下角缩放,那么右上角就是静止不动的点)
QPointF staticPos;
// 鼠标点cursorPos所在的角的顶点坐标(指的是BlockItem的角的坐标,注意不是cursorPos因为有一点偏移量)
// 此版本还没开发这个偏移功能,有了这个功能在缩放时鼠标的样式就不会改变了(还有一个方案,可以尝试,就是将SquareItem设置为可选择可移动,以此来缩放)
QPointF movePos;
// 理论上缩放后最小的点坐标
QPointF minPos;
qreal blockWidth,blockHeight;
// 限制最小缩放大小坐标数值
qreal x,y;
squareItemDirection = squareItem->data(ITEM_TYPE).toInt();
oldBlockPos = m_BlockItem->scenePos();
blockWidth = m_BlockItem->boundingRect().width();
blockHeight = m_BlockItem->boundingRect().height();
switch (squareItemDirection)
{
case EnumType::SquareItem_LeftTop:
// 缩放时静止不动的点:即BlockItem右下角点坐标
staticPos = oldBlockPos + QPointF(blockWidth,blockHeight);
minPos = staticPos + QPointF( -100.0, -50.0);
// 限制缩放最小大小
x = (cursorPos.rx() >= minPos.rx() ? minPos.rx() : cursorPos.rx());
y = (cursorPos.ry() >= minPos.ry() ? minPos.ry() : cursorPos.ry());
movePos = QPointF(x,y);
newBlockPos = movePos;
blockWidth = staticPos.rx() - movePos.rx();
blockHeight = staticPos.ry() - movePos.ry();
break;
case EnumType::SquareItem_LeftBottom:
// 缩放时静止不动的点:即BlockItem右上角点坐标
staticPos = oldBlockPos + QPointF(blockWidth,0.0);
minPos = staticPos + QPointF(-100.0, +50);
// 限制缩放最小大小
x = (cursorPos.rx() >= minPos.rx() ? minPos.rx() : cursorPos.rx());
y = (cursorPos.ry() <= minPos.ry() ? minPos.ry() : cursorPos.ry());
movePos = QPointF(x,y);
newBlockPos = QPointF(movePos.rx(),staticPos.ry());
blockWidth = staticPos.rx() - movePos.rx();
blockHeight = movePos.ry() - staticPos.ry();
break;
case EnumType::SquareItem_RightBottom:
// 缩放时静止不动的点:即BlockItem左上角点坐标
staticPos = oldBlockPos;
minPos = staticPos + QPointF(+100.0, +50.0);
// 限制缩放最小大小
x = (cursorPos.rx() <= minPos.rx() ? minPos.rx() : cursorPos.rx());
y = (cursorPos.ry() <= minPos.ry() ? minPos.ry() : cursorPos.ry());
movePos = QPointF(x,y);
newBlockPos = oldBlockPos;
blockWidth = movePos.rx() - staticPos.rx() ;
blockHeight = movePos.ry() - staticPos.ry() ;
break;
case EnumType::SquareItem_RightTop:
// 缩放时静止不动的点:即BlockItem左下角点坐标
staticPos = oldBlockPos + QPointF(0.0,blockHeight);
minPos = staticPos + QPointF(+100.0,-50.0);
// 限制缩放最小大小
x = (cursorPos.rx() <= minPos.rx() ? minPos.rx() : cursorPos.rx());
y = (cursorPos.ry() >= minPos.ry() ? minPos.ry() : cursorPos.ry());
movePos = QPointF(x,y);
newBlockPos = QPointF(staticPos.rx(),movePos.ry());
blockWidth = movePos.rx() - staticPos.rx();
blockHeight = staticPos.ry() - movePos.ry();
break;
default:
break;
}
// 设置BlockItem新的坐标点
m_BlockItem->setPos(newBlockPos);
// 这里的setWidth()是我的自定义类(FlowBlockItem)里面的自己写的函数(见下面的代码片段)
m_BlockItem->setWidth(blockWidth);
m_BlockItem->setHeight(blockHeight);
// 下面三个分别是都是更新缩放后的坐标
updateSquareItem();
updateDotItem();
updateTextItem();
}
FlowBlockItem自定义类
void FlowBlockItem::setHeight(const qreal &Height)
{
m_Height = Height;
}
void FlowBlockItem::setWidth(const qreal &Width)
{
m_Width = Width;
}
// 继承重写函数(所有绘制都要被限制在这个矩形内部)
QRectF FlowBlockItem::boundingRect(void) const
{
// 设置Item的矩形默认大小
return QRectF(0,0,m_Width,m_Height);
}