Qt C++之QGraphicsItem的缩放(包含源代码)
在QGraphicsScene中,拖动鼠标缩放矩形QGraphicsRectItem的技术探索需求:1.QGraphicsRectItem m_BlockItem是需要缩放的矩形;2.鼠标左击按住矩形四个角后拖动,矩形m_BlockItem做相应的放大和缩小;3.左边的小三角形还需要保持在左边中点附近;思路:1.先新建一个QGraphicsRectItem m_BlockItem,作为大矩形(目标
·
在QGraphicsScene中,拖动鼠标缩放矩形QGraphicsRectItem的技术探索
需求:
1.QGraphicsRectItem m_BlockItem是需要缩放的矩形;
2.鼠标左击按住矩形四个角后拖动,矩形m_BlockItem做相应的放大和缩小;
3.左边的小三角形还需要保持在左边中点附近;
思路:
1.先新建一个QGraphicsRectItem m_BlockItem,作为大矩形(目标矩形);
2.在创建四个小正方形QGraphicsRectItem m_SmallRect_0、m_SmallRect_1、m_SmallRect_2、m_SmallRect_3,分别对应m_BlockItem的左上角、右上角、右下角和左下角,然后使用:setParentItem(m_BlockItem)函数,将四个小矩形放入m_BlockItem中。
如有不懂欢迎回复交流:邮箱:xingyu.cat@foxmail.com
运行效果图:
上代码:
SimuLinkScene.h
#ifndef SIMULINKSCENE_H
#define SIMULINKSCENE_H
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsSimpleTextItem>
#include <QGraphicsPolygonItem>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
class SimuLinkScene : public QGraphicsScene
{
Q_OBJECT
public:
explicit SimuLinkScene(QObject *parent = Q_NULLPTR);
int cursorType = 0;
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
private:
//目标大矩形的
QGraphicsRectItem *m_BlockItem;
//矩形的名称
QGraphicsSimpleTextItem *m_BlockNameTextItem;
//矩形左边的小三角形
QGraphicsPolygonItem *m_PortItem;
QGraphicsRectItem *m_SmallRect_0;
QGraphicsRectItem *m_SmallRect_1;
QGraphicsRectItem *m_SmallRect_2;
QGraphicsRectItem *m_SmallRect_3;
// m_BlockItem的左上角在场景中的坐标
QPointF point1;
// m_BlockItem的右下角在场景中的坐标
QPointF point2;
//标记鼠标是否被按下
bool m_LeftButton_IsPressed = false;
};
#endif // SIMULINKSCENE_H
SimuLinkScene.cpp
#include "SimuLinkScene.h"
SimuLinkScene::SimuLinkScene(QObject *parent )
{
Q_UNUSED(parent);
this->setSceneRect(0, 0, 6000, 1200);
m_BlockItem = new QGraphicsRectItem;
m_BlockNameTextItem = new QGraphicsSimpleTextItem;
m_PortItem = new QGraphicsPolygonItem;
m_SmallRect_0 = new QGraphicsRectItem;
m_SmallRect_1 = new QGraphicsRectItem;
m_SmallRect_2 = new QGraphicsRectItem;
m_SmallRect_3 = new QGraphicsRectItem;
// 用于判断是哪个类型的Item
m_BlockItem->setData(1,1);
m_BlockNameTextItem->setData(1,2);
m_PortItem->setData(1,3);
m_SmallRect_0->setData(1,4);
m_SmallRect_1->setData(1,4);
m_SmallRect_2->setData(1,4);
m_SmallRect_3->setData(1,4);
// 这是矩形框线的粗细
int item_width = 1;
QPen pen(Qt::black, item_width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
// 前两个参数:表示放入父项目的坐标(如果没有父项目就是对应场景中坐标)
// 后两个参数:表示宽和高
m_BlockItem->setRect(0,0,150,80);
m_BlockItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
// 将m_BlockNameTextItem放入到m_BlockItem中,此时m_BlockNameTextItem就有了父类调用setPos的坐标都是相对于m_BlockItem的左上角来的
m_BlockNameTextItem->setParentItem(m_BlockItem);
m_BlockNameTextItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
QFont font = m_BlockNameTextItem->font();
// 像素大小
font.setPixelSize(10);
// font.setItalic(true); // 斜体
// font.setUnderline(true); // 下划线
m_BlockNameTextItem->setFont(font);
m_BlockNameTextItem->setText("ttt");
m_BlockNameTextItem->setPos(37.5,40);
// 将m_PortItem放入到m_BlockItem中,此时m_PortItem就有了父类调用setPos的坐标都是相对于m_BlockItem的左上角来的
m_PortItem->setParentItem(m_BlockItem);
// 因为多边形需要通过坐标数组
QVector<QPointF> v_point;
v_point.append(QPointF(0,40));
v_point.append(QPointF(-10,30));
v_point.append(QPointF(-10,50));
m_PortItem->setPolygon(v_point);
m_PortItem->setZValue(1);
m_PortItem->setPen(QPen(Qt::black, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
// 将m_SmallRect_0放入到m_BlockItem中,此时m_SmallRect_0就有了父类调用setPos的坐标都是相对于m_BlockItem的左上角来的
m_SmallRect_0->setParentItem(m_BlockItem);
m_SmallRect_1->setParentItem(m_BlockItem);
m_SmallRect_2->setParentItem(m_BlockItem);
m_SmallRect_3->setParentItem(m_BlockItem);
//设置项目Item可以被选择和可以成为焦点项
m_SmallRect_0->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
m_SmallRect_1->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
m_SmallRect_2->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
m_SmallRect_3->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
// 设置m_SmallRect_0的图层级别,数值越大越在最上面,默认是0
m_SmallRect_0->setZValue(2);
m_SmallRect_1->setZValue(2);
m_SmallRect_2->setZValue(2);
m_SmallRect_3->setZValue(2);
// 标记m_SmallRect_0在哪个角(0对应左上角、1对应右上角、2对应右下角、3对应左下角)
m_SmallRect_0->setData(3,0);
m_SmallRect_1->setData(3,1);
m_SmallRect_2->setData(3,2);
m_SmallRect_3->setData(3,3);
// 设置m_SmallRect_0的边框线
m_SmallRect_0->setPen(pen);
m_SmallRect_1->setPen(pen);
m_SmallRect_2->setPen(pen);
m_SmallRect_3->setPen(pen);
// m_SmallRect_0的左上角画在以m_BlockItem的左上角为原点的(-4,-4)处。宽为8,高为8
m_SmallRect_0->setRect(-4,-4,8,8);
m_SmallRect_1->setRect(146,-4,8,8);
m_SmallRect_2->setRect(146,76,8,8);
m_SmallRect_3->setRect(-4,76,8,8);
this->addItem(m_BlockItem);
}
void SimuLinkScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsScene::mousePressEvent(event);
QGraphicsItem *item = focusItem();
qDebug()<<"获取对象"<<item->data(1).toInt();
qDebug()<<"width:"<<m_BlockItem->boundingRect().width()<<";height:"<<m_BlockItem->boundingRect().height();
qDebug()<<"TextItemPos:"<<m_BlockNameTextItem->mapToScene(m_BlockNameTextItem->pos().x(),m_BlockNameTextItem->pos().y())-m_BlockNameTextItem->pos()<<";Pos:"<<m_BlockNameTextItem->pos();
qDebug()<<"m_BlockItem_pos:"<<m_BlockItem->scenePos();
qDebug()<<"Cursor:"<<event->scenePos();
// 要用setX和setY不要使用 point1 = QPointF(x,y);
// m_BlockItem->scenePos():是m_BlockItem左上角的点在场景Scene中的坐标
point1.setX(m_BlockItem->scenePos().x());
point1.setY(m_BlockItem->scenePos().y());
point2.setX(m_BlockItem->scenePos().x()+m_BlockItem->boundingRect().width());
point2.setY(m_BlockItem->scenePos().y()+m_BlockItem->boundingRect().height());
qDebug()<<"point1="<<point1;
qDebug()<<"point2="<<point2;
if(event->button() == Qt::LeftButton)
{
m_LeftButton_IsPressed = true;
}
}
void SimuLinkScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsScene::mouseReleaseEvent(event);
if(event->button() == Qt::LeftButton)
{
m_LeftButton_IsPressed = false;
}
}
void SimuLinkScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsScene::mouseDoubleClickEvent(event);
}
void SimuLinkScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsScene::mouseMoveEvent(event);
// 获取场景中的焦点Item,需要Item设置该属性 item->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
QGraphicsItem *currentItem = focusItem();
// 至于这里的点为什么使用qreal(double)型,参考该博主:https://blog.csdn.net/m0_37545861/article/details/117930243?spm=1001.2014.3001.5501
qreal scene_X = event->scenePos().x();
qreal scene_Y = event->scenePos().y();
// 如果小正方形被鼠标点击了成为了焦点item,
if( currentItem!=nullptr && currentItem->data(1).toInt() == 4 && m_LeftButton_IsPressed){
int type = currentItem->data(3).toInt();
switch (type) {
// 如果点击的是左上角的小正方形
case 0:
cursorType = 0;
// 矩形的左上角坐标是光标的坐标
point1.setX(scene_X); //注意这里的是场景中光标的坐标
point1.setY(scene_Y);
// 矩形左下角不变
point2.setX(point2.x());
point2.setY(point2.y());
m_BlockItem->setRect(0,0,point2.x()-point1.x(),point2.y()-point1.y());
m_BlockItem->setPos(point1);
m_SmallRect_0->setRect(-4,-4,8,8);
m_SmallRect_1->setRect(m_BlockItem->boundingRect().width()-4,-4,8,8);
m_SmallRect_2->setRect(m_BlockItem->boundingRect().width()-4,m_BlockItem->boundingRect().height()-4,8,8);
m_SmallRect_3->setRect(-4,m_BlockItem->boundingRect().height()-4,8,8);
break;
// 如果点击的是右上角的小正方形
case 1:
cursorType = 1;
// 左上角的x坐标还是原来的x坐标
point1.setX(point1.x());
// 左上角的Y坐标需要跟随光标的Y坐标
point1.setY(scene_Y);
point2.setX(scene_X);
point2.setY(point2.y());
m_BlockItem->setRect(0,0,point2.x()-point1.x(),point2.y()-point1.y());
m_BlockItem->setPos(point1);
m_SmallRect_0->setRect(-4,-4,8,8);
m_SmallRect_1->setRect(m_BlockItem->boundingRect().width()-4,-4,8,8);
m_SmallRect_2->setRect(m_BlockItem->boundingRect().width()-4,m_BlockItem->boundingRect().height()-4,8,8);
m_SmallRect_3->setRect(-4,m_BlockItem->boundingRect().height()-4,8,8);
break;
// 如果点击的是右下角的小正方形
case 2:
cursorType = 0;
point1.setX(point1.x());
point1.setY(point1.y());
point2.setX(scene_X);
point2.setY(scene_Y);
m_BlockItem->setRect(0,0,point2.x()-point1.x(),point2.y()-point1.y());
m_BlockItem->setPos(point1);
m_SmallRect_0->setRect(-4,-4,8,8);
m_SmallRect_1->setRect(m_BlockItem->boundingRect().width()-4,-4,8,8);
m_SmallRect_2->setRect(m_BlockItem->boundingRect().width()-4,m_BlockItem->boundingRect().height()-4,8,8);
m_SmallRect_3->setRect(-4,m_BlockItem->boundingRect().height()-4,8,8);
break;
case 3:
cursorType = 1;
point1.setX(scene_X);
point1.setY(point1.y());
point2.setX(point2.x());
point2.setY(scene_Y);
m_BlockItem->setRect(0,0,point2.x()-point1.x(),point2.y()-point1.y());
m_BlockItem->setPos(point1);
m_SmallRect_0->setRect(-4,-4,8,8);
m_SmallRect_1->setRect(m_BlockItem->boundingRect().width()-4,-4,8,8);
m_SmallRect_2->setRect(m_BlockItem->boundingRect().width()-4,m_BlockItem->boundingRect().height()-4,8,8);
m_SmallRect_3->setRect(-4,m_BlockItem->boundingRect().height()-4,8,8);
break;
default:
break;
}
QVector<QPointF> v_point;
v_point.append(QPointF(0,m_BlockItem->boundingRect().height()/2));
v_point.append(QPointF(-10,m_BlockItem->boundingRect().height()/2-10));
v_point.append(QPointF(-10,m_BlockItem->boundingRect().height()/2+10));
m_PortItem->setPolygon(v_point);
QPointF p1 = QPointF(m_BlockItem->boundingRect().width()/2-m_BlockNameTextItem->boundingRect().width()/2,m_BlockItem->boundingRect().height());
m_BlockNameTextItem->setPos(p1);
}
}
void SimuLinkScene::keyPressEvent(QKeyEvent *event)
{
QGraphicsScene::keyPressEvent(event);
}
更多推荐
所有评论(0)