系列文章目录
QGraphicsItem图元的简单使用(一)
QGraphicsItem图元拖动绘制(二)
QGraphicsItem图元旋转缩放和自定义图元(三)
前言
接上一篇,本章将讲解如何通过鼠标拖动图元进行缩放拉伸
一、演示效果
二、相关代码
需要先在打开图元接受鼠标悬浮事件的开关,构造函数中添加如下代码:
// 接收鼠标悬浮事件
this->setAcceptHoverEvents(true);
计算鼠标各个悬浮区域,鼠标悬浮时,显示不同的鼠标样式
void RectItem::UpdateHandlesArea()
{
QRectF rect = this->boundingRect();
m_handlesArea[Mouse_LeftTop] = QRectF(rect.left(), rect.top(), m_dHandleSize, m_dHandleSize); // 左上
m_handlesArea[Mouse_RightTop] = QRectF(rect.right() - m_dHandleSize, rect.top(), m_dHandleSize, m_dHandleSize); // 右上
m_handlesArea[Mouse_LeftBottom] = QRectF(rect.left(), rect.bottom() - m_dHandleSize, m_dHandleSize, m_dHandleSize); // 左下
m_handlesArea[Mouse_RightBottom] = QRectF(rect.right() - m_dHandleSize, rect.bottom() - m_dHandleSize, m_dHandleSize, m_dHandleSize); // 右下
m_handlesArea[Mouse_MiddleTop] = QRectF(rect.center().x() - m_dHandleSize / 2, rect.top(), m_dHandleSize, m_dHandleSize); // 中上
m_handlesArea[Mouse_MiddleBottom] = QRectF(rect.center().x() - m_dHandleSize / 2, rect.bottom() - m_dHandleSize, m_dHandleSize, m_dHandleSize);
m_handlesArea[Mouse_MiddleLeft] = QRectF(rect.left(), rect.center().y() - m_dHandleSize / 2, m_dHandleSize, m_dHandleSize); // 中左
m_handlesArea[Mouse_MiddleRight] = QRectF(rect.right() - m_dHandleSize, rect.center().y() + m_dHandleSize / 2, m_dHandleSize, m_dHandleSize);
}
鼠标相关事件重写
void RectItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
if(this->isSelected())
{
m_eMouseHandle = GetMouseHandle(event->pos());
switch (m_eMouseHandle) {
case Mouse_LeftTop: // 左上
case Mouse_RightBottom: // 右下
this->setCursor(Qt::SizeFDiagCursor);
break;
case Mouse_LeftBottom: // 左下
case Mouse_RightTop: // 右上
this->setCursor(Qt::SizeBDiagCursor);
break;
case Mouse_MiddleTop: // 上
case Mouse_MiddleBottom: // 下
this->setCursor(Qt::SizeVerCursor);
break;
case Mouse_MiddleLeft: // 左
case Mouse_MiddleRight: // 右
this->setCursor(Qt::SizeHorCursor);
break;
default:
this->setCursor(Qt::SizeAllCursor);
break;
}
}
return QGraphicsItem::hoverEnterEvent(event);
}
void RectItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
m_eMouseHandle = Mouse_None; // 无
this->setCursor(Qt::ArrowCursor);
return QGraphicsItem::hoverLeaveEvent(event);
}
void RectItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) // 左键按下
{
// 当前选中图形边缘,进行图元尺寸改变处理
if(m_eMouseHandle != Mouse_None)
{
m_pressRect = boundingRect();
return;
}
}
return QGraphicsItem::mousePressEvent(event);
}
void RectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() == Qt::LeftButton) // 左键按下
{
// 处理鼠标第一次绘制时的拖动
if(m_bDrawFlag)
{
return;
}
// 处理鼠标拖动缩放图元时绘制
if(m_eMouseHandle != Mouse_None)
{
ResizeRect(event->pos());
return;
}
}
return QGraphicsItem::mouseMoveEvent(event);
}
void RectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
// 防止鼠标右键弹出菜单后,左击移动
if (event->button() == Qt::LeftButton) // 左键按下
{
// 只处理上下拖动
if(m_eMouseHandle != Mouse_None)
{
// 拖动结束后恢复选中
this->setSelected(true);
}
}
return QGraphicsItem::mouseReleaseEvent(event);
}
缩放函数如下
void RectItem::ResizeRect(const QPointF &mousePos)
{
// 当前无操作,直接返回
if(m_eMouseHandle == Mouse_None)
{
return;
}
// 准备变化
this->prepareGeometryChange();
QRectF rect = m_rect;
qreal dMouseX = mousePos.x(); // 鼠标当前的y坐标
qreal dMouseY = mousePos.y(); // 鼠标当前的y坐标
const qreal dMixSize = 2.0 * (1 + m_dAdjust); // 收缩时的最小尺寸
// 当前剩余的高度和宽度
double dRemainWidth = m_pressRect.width();
double dRemainHeight = m_pressRect.height();
if(m_eMouseHandle == Mouse_LeftTop || m_eMouseHandle == Mouse_MiddleLeft || m_eMouseHandle == Mouse_MiddleTop) // 鼠标在左上、左、上
{ // 右下角的点保持不变
// 向上拉伸缩放宽度是不变的
if(m_eMouseHandle != Mouse_MiddleTop)
{
// 剩余宽度=矩形右边x坐标-鼠标移动当前x
dRemainWidth = m_pressRect.right() - dMouseX;
if(dRemainWidth < dMixSize)
{
dRemainWidth = dMixSize;
}
}
// 向左拉伸缩放高度是不变的
if(m_eMouseHandle != Mouse_MiddleLeft)
{
// 剩余高度=矩形底部y-鼠标移动当前y
dRemainHeight = m_pressRect.bottom() - dMouseY;
if(dRemainHeight < dMixSize)
{
dRemainHeight = dMixSize;
}
}
// 如果宽度或者高度缩放到最小值,则不让再缩放了
if(dRemainWidth > dMixSize && dRemainHeight > dMixSize)
{
// 计算左上角的坐标
rect.setTopLeft(QPointF(m_pressRect.right() - dRemainWidth, m_pressRect.bottom() - dRemainHeight));
}
}
else if(m_eMouseHandle == Mouse_LeftBottom || m_eMouseHandle == Mouse_MiddleBottom) // 鼠标在左下、下
{ // 保持右上角不变
// 向下拉伸缩放宽度是不变的
if(m_eMouseHandle != Mouse_MiddleBottom)
{
// 剩余宽度=矩形右边x坐标-鼠标移动当前x
dRemainWidth = m_pressRect.right() - dMouseX;
if(dRemainWidth < dMixSize)
{
dRemainWidth = dMixSize;
}
}
// 剩余高度=矩形底部y-鼠标移动当前y
dRemainHeight = dMouseY - m_pressRect.top();
if(dRemainHeight < dMixSize)
{
dRemainHeight = dMixSize;
}
// 如果宽度或者高度缩放到最小值,则不让再缩放了
if(dRemainWidth > dMixSize && dRemainHeight > dMixSize)
{
// 计算左下角的坐标
rect.setBottomLeft(QPointF(m_pressRect.right() - dRemainWidth, m_pressRect.top() + dRemainHeight));
}
}
else if(m_eMouseHandle == Mouse_RightBottom || m_eMouseHandle == Mouse_MiddleRight) // 鼠标在右下、右
{ // 保持左上角落不变
// 剩余宽度=鼠标移动当前x坐标-矩形左边x坐标
dRemainWidth = dMouseX - m_pressRect.left();
if(dRemainWidth < dMixSize)
{
dRemainWidth = dMixSize;
}
// 向右拉伸缩放高度是不变的
if(m_eMouseHandle != Mouse_MiddleRight)
{
// 剩余高度=矩形底部y-鼠标移动当前y
dRemainHeight = dMouseY - m_pressRect.top();
if(dRemainHeight < dMixSize)
{
dRemainHeight = dMixSize;
}
}
// 如果宽度或者高度缩放到最小值,则不让再缩放了
if(dRemainWidth > dMixSize && dRemainHeight > dMixSize)
{
// 计算右下角的坐标
rect.setBottomRight(QPointF(m_pressRect.left() + dRemainWidth, m_pressRect.top() + dRemainHeight));
}
}
else if(m_eMouseHandle == Mouse_RightTop) // 右上
{ // 保持左下角不变
// 剩余宽度=矩形右边x坐标-鼠标移动当前x
dRemainWidth = dMouseX - m_pressRect.left();
if(dRemainWidth < dMixSize)
{
dRemainWidth = dMixSize;
}
// 剩余高度=矩形底部y-鼠标移动当前y
dRemainHeight = m_pressRect.bottom() - dMouseY;
if(dRemainHeight < dMixSize)
{
dRemainHeight = dMixSize;
}
// 如果宽度或者高度缩放到最小值,则不让再缩放了
if(dRemainWidth >= dMixSize && dRemainHeight >= dMixSize)
{
// 计算右上角的坐标
rect.setTopRight(QPointF(m_pressRect.left() + dRemainWidth, m_pressRect.bottom() - dRemainHeight));
}
}
this->setRect(rect);
}
总结
该章简单讲解了一下如何拖动图元进行缩放,下章将继续讲解如果拖动旋转图元文章来源:https://www.toymoban.com/news/detail-502114.html
整个工程 示例源码 下载文章来源地址https://www.toymoban.com/news/detail-502114.html
到了这里,关于QGraphicsItem鼠标拖动图元进行缩放拉伸(四)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!