系列文章目录
前言
接上一章,上一章讲解了如何简单使用图元,通过鼠标点击绘制一个固定图元,该章将讲解如何通过鼠标拖动图元进行绘制
一、简单演示
二、实现代码
接上一章,需要重写场景类的鼠标按下和鼠标移动事件,具体代码如下
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
// 记录鼠标按下起始位置
m_startPos = event->scenePos();
switch (m_eGraphicsType) {
case Rect:
{
// 不传参,默认起点、长宽为0
m_pCurRect = new QGraphicsRectItem();
// 设置可移动、可选择
m_pCurRect->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
this->addItem(m_pCurRect);
// 设置图元在场景中的位置,即鼠标点击位置
m_pCurRect->setPos(m_startPos);
}
break;
case Circle:
{
m_pCurEllipse = new QGraphicsEllipseItem();
// 设置可移动、可选择
m_pCurEllipse->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
this->addItem(m_pCurEllipse);
m_pCurEllipse->setPos(m_startPos);
}
break;
case Line:
{
m_pCurLine = new QGraphicsLineItem();
// 设置可移动、可选择
m_pCurLine->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
this->addItem(m_pCurLine);
m_pCurLine->setPos(m_startPos);
}
break;
case Text:
{
QGraphicsTextItem* pText = new QGraphicsTextItem();
// 设置可移动、可选择
pText->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
// 设置文本图元可接受鼠标、键盘的编辑
pText->setTextInteractionFlags(Qt::TextEditorInteraction);
// 设置文本图元的堆叠顺序,如果两个图元叠加在一起,值越大的在上面
pText->setZValue(1000.0);
this->addItem(pText);
pText->setPos(m_startPos.x() - pText->boundingRect().width() / 2.0, m_startPos.y() - pText->boundingRect().height() / 2.0);
}
break;
case Pixmap:
{
QGraphicsPixmapItem* pPixmap = new QGraphicsPixmapItem(QPixmap(u8":/image/dog.png"));
// 设置可移动、可选择
pPixmap->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
this->addItem(pPixmap);
pPixmap->setPos(m_startPos.x() - pPixmap->boundingRect().width() / 2.0, m_startPos.y() - pPixmap->boundingRect().height() / 2.0);
}
break;
default:
break;
}
return QGraphicsScene::mousePressEvent(event);
}
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QPointF curPos = event->scenePos();
switch (m_eGraphicsType) {
case Rect:
{
// 通过左上和右下点来确定绘制一个矩形
qreal dTopLeftX{0}, dTopLeftY{0}, dBottomRightX{0}, dBottomRightY{0};
// 因为鼠标左键点击时,创建了一个空的矩形图元,默认矩形本身的起始坐标为(0,0),有四个方向可以拖动绘制(左上、左下、右上、右下),所以需要重新设置图元的起始坐标
if(curPos.x() < m_startPos.x() && curPos.y() < m_startPos.y()) // 鼠标左上方向拖动
{
// 先确定左上角的点,右下角为(0,0)
dTopLeftX = curPos.x() - m_startPos.x();
dTopLeftY = curPos.y() - m_startPos.y();
}
else if(curPos.x() < m_startPos.x() && curPos.y() > m_startPos.y()) // 鼠标左下方向拖动
{
// 先确定左上角的点的x坐标
dTopLeftX = curPos.x() - m_startPos.x();
// 再确定右下角的点的y坐标
dBottomRightY = curPos.y() - m_startPos.y();
}
else if(curPos.x() > m_startPos.x() && curPos.y() < m_startPos.y()) // 鼠标右上方向拖动
{
// 先确定左上角的点的y坐标
dTopLeftY = curPos.y() - m_startPos.y();
// 再确定右下角的点的x坐标
dBottomRightX = curPos.x() - m_startPos.x();
}
else if(curPos.x() > m_startPos.x() && curPos.y() > m_startPos.y()) // 鼠标右下方向拖动
{
// 先确定右下角的点,左上角为(0,0)
dBottomRightX = curPos.x() - m_startPos.x();
dBottomRightY = curPos.y() - m_startPos.y();
}
m_pCurRect->setRect(QRectF(QPointF(dTopLeftX, dTopLeftY), QPointF(dBottomRightX, dBottomRightY)));
}
break;
case Circle:
{
// 椭圆内部做了处理,不需向矩形一样重新计算起点坐标和宽高
m_pCurEllipse->setRect(m_pCurEllipse->rect().x(), m_pCurEllipse->rect().y(), curPos.x() - m_startPos.x(), curPos.y() - m_startPos.y());
}
break;
case Line:
{
// p1时线的起点,也就是(0,0),通过相减所得的相对偏移为线的终点
m_pCurLine->setLine(QLineF(m_pCurLine->line().p1(), curPos - m_startPos));
}
break;
default:
break;
}
return QGraphicsScene::mouseMoveEvent(event);
}
总结
该章讲解了如何拖动绘制矩形、椭圆和线,以及点击手动输入文本,Qt自带的图像图元因为没有提供相关设置接口,无法拖动绘制,需要自己派生QGraphicsItem图元实现,后面再将