#include #include "ZxBaseUtil.h" #include "nmObjRound.h" #include "nmObjRoundTool.h" #include nmObjRoundTool::nmObjRoundTool() : nmObjToolBase() { setText(tr("nObjRoundTool")); m_oNot = NMOT_Round; } bool nmObjRoundTool::onLeftDown(const QPointF& pt) { if (NULL == m_pObj) // 绘图对象尚未创建(鼠标选点ing) { m_bTracking = true; m_ptStart = pt; changeCursor(Qt::CrossCursor); // 对于正在创建选择的工具,需要保持光标 getView()->setCursorKeeping(true); //m_vecPoints.push_back(pt); return true; } else // 已绑定绘图对象 { return nmObjToolBase::onLeftDown(pt); } } bool nmObjRoundTool::onMouseMove(const QPointF& pt) { if (NULL == m_pObj) // 绘图对象尚未创建(鼠标选点ing) { m_ptMove = pt; if (m_bTracking) { // 更新渲染区域 updateLastMoveArea(true); } return true; } else // 已绑定绘图对象 { return nmObjToolBase::onMouseMove(pt); } } bool nmObjRoundTool::onLeftUp(const QPointF& pt) { if (NULL == m_pObj) // 绘图对象尚未创建(鼠标选点ing) { // 鼠标抬起说明创建已经完成 getView()->setCursorKeeping(false); changeCursor(Qt::ArrowCursor); // 圆形依赖拖拽成形,起点和终点过近时取消本次创建,避免双击或误点生成零尺寸图元。 double dDistance = 2.2f; if ((qAbs(m_ptStart.x() - pt.x()) < dDistance) && (qAbs(m_ptStart.y() - pt.y()) < dDistance)) { m_vecPoints.clear(); m_bTracking = false; return true; } // 计算圆心的位置 m_ptMove = pt; QPointF m_ptCenter((m_ptStart.x() + m_ptMove.x()) / 2,(m_ptStart.y() + m_ptMove.y()) / 2); // 计算半径 qreal dx = m_ptMove.x() - m_ptStart.x(); qreal dy = m_ptMove.y() - m_ptStart.y(); qreal radius = sqrt(pow(dx, 2) + pow(dy, 2)) / 2; //根据半径和圆心计算圆上的四个关键点 QPointF m_ptTop(m_ptCenter.x(),m_ptCenter.y()-radius),\ m_ptRight(m_ptCenter.x() + radius,m_ptCenter.y()),\ m_ptBottom(m_ptCenter.x(),m_ptCenter.y() + radius),\ m_ptLeft(m_ptCenter.x() - radius,m_ptCenter.y()); // 保存圆心和半径 m_vecPoints.push_back(m_ptCenter); //vector[0] QPointF m_ptRadius(radius,radius); // 将半径以点的方式保存 m_vecPoints.push_back(m_ptRadius);//vector[1] // 按顺序保存四个关键点 m_vecPoints.push_back(m_ptTop); //vector[2] m_vecPoints.push_back(m_ptRight); // vector[3] m_vecPoints.push_back(m_ptBottom); //vector[4] m_vecPoints.push_back(m_ptLeft); // //vector[5] emit sigPtsFinished(m_vecPoints); // 注意这个信号执行后,会被nmObjRoundTool的View detach m_vecPoints.clear(); m_bTracking = false; return true; } else // 已绑定绘图对象 { return nmObjToolBase::onLeftUp(pt); } } bool nmObjRoundTool::onLeftDoubleClick(const QPointF& pt) { if(NULL == m_pObj) { // 绘图对象尚未创建(鼠标选点ing) // 圆形创建不依赖双击收尾,创建态直接吞掉双击事件。 return true; } else { // 已绑定绘图对象 // 双击内部,取消选中状态 if (m_pObj->m_oHitOption == OHO_Inner) { m_pObj->setSelected(false); return true; } return nmObjToolBase::onLeftDoubleClick(pt); } } void nmObjRoundTool::onPaint(QPainter* painter, const ZxPaintParam& param) { nmObjRound* pObj = dynamic_cast(m_pObj); if (pObj == NULL) // 绘图对象尚未创建(鼠标选点ing) { Qt::CursorShape o = Qt::CrossCursor; changeCursor(o); paintTrackingVirtualObj(painter, param); } else // 已绑定绘图对象 { paintTrackingRealObj(painter, param); } } void nmObjRoundTool::paintTrackingVirtualObj(QPainter* painter, const ZxPaintParam& param) { painter->save(); // 当前正在创建的点 if (m_bTracking || !m_vecPoints.isEmpty()) { QPen pen(Qt::DashLine); painter->setPen(pen); // 计算圆心的位置 QPointF m_ptCenter((m_ptStart.x() + m_ptMove.x()) / 2,(m_ptStart.y() + m_ptMove.y()) / 2); // 计算半径 qreal dx = m_ptMove.x() - m_ptStart.x(); qreal dy = m_ptMove.y() - m_ptStart.y(); qreal radius = sqrt(pow(dx, 2) + pow(dy, 2)) / 2; // 绘制圆 painter->drawEllipse(m_ptCenter,radius,radius); } painter->restore(); } void nmObjRoundTool::paintTrackingRealObj(QPainter* painter, const ZxPaintParam& param) { if (!m_bTracking) { return; } nmObjRound* pObj = dynamic_cast(m_pObj); Q_ASSERT(pObj != nullptr); if (nullptr == pObj) { return; // 如果pObj为nullptr,直接返回 } // 获取当前命中位置和光标形状 Qt::CursorShape cursor = getCursorBy(static_cast(m_oHitOption), pObj->m_nHitIndex); QVector vec = pObj->getAllPos(); // 判断半径是否相同,不相同先修改半径相同 if (vec[1].x() != vec[1].y()) { double radius = qAbs(vec[0].y() - vec[2].y()); vec[1] = QPointF(radius, radius); } QPointF ptOld = m_ptStart; // 拖动起始点 QPointF ptNew = getCurrentPos(); // 当前鼠标位置 QPointF& center = vec[0]; // 圆心 QPointF& radiusPoint = vec[1]; // 半径(x和y相同,因为是正圆) // 根据命中位置调整圆形 switch (m_oHitOption) { case OHO_Point: // 边缘点拖动:调整半径 { // 计算新半径(圆心到当前鼠标位置的距离) qreal newRadius = QLineF(center, ptNew).length(); // 更新半径(保持x和y相同) radiusPoint.setX(newRadius); radiusPoint.setY(newRadius); // 更新四个边缘点位置 vec[2] = QPointF(center.x(), center.y() - newRadius); // 上 vec[3] = QPointF(center.x() + newRadius, center.y()); // 右 vec[4] = QPointF(center.x(), center.y() + newRadius); // 下 vec[5] = QPointF(center.x() - newRadius, center.y()); // 左 break; } case OHO_Inner: // 内部拖动:移动整个圆 { QPointF offset = ptNew - ptOld; center += offset; // 更新所有边缘点 qreal radius = radiusPoint.x(); vec[2] += offset; // 上 vec[3] += offset; // 右 vec[4] += offset; // 下 vec[5] += offset; // 左 break; } default: return; // 其他情况不处理 } // 绘制圆形 painter->save(); QPen pen(Qt::DashLine); painter->setPen(pen); // 绘制圆形路径并填充半透明背景 QPainterPath path; path.addEllipse(center, radiusPoint.x(), radiusPoint.y()); QColor bgColor = pObj->getBackgrdColor(); bgColor.setAlpha(128); // 设置透明度 painter->fillPath(path, bgColor); painter->drawPath(path); // 更新光标形状 changeCursor(cursor); painter->restore(); } Qt::CursorShape nmObjRoundTool::getCursorBy(const int& nOption, const int& nSubIndex) { if (nOption < 0) { return Qt::ArrowCursor; } // 选择状态下起作用 if (!m_pObj->isSelected()) { return Qt::ArrowCursor; } ObjHitOption oHitOption = (ObjHitOption)nOption; if(oHitOption == OHO_Point) { return (Qt::CrossCursor); } else if(oHitOption == OHO_Bound) { return (Qt::ArrowCursor); } else if (oHitOption == OHO_Inner) { return (Qt::PointingHandCursor); } return Qt::ArrowCursor; }