123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #include "WindowAppItemLinkLine.h"
- #include "WindowAppItemLink.h"
- WindowAppItemLinkLine::WindowAppItemLinkLine(
- QPointF ptStart,
- QPointF ptEnd,
- QGraphicsItemGroup* parent,
- LINK_MODE linkMode
- )
- : m_bLinkEndLine(false)
- , m_bLinkStartLine(false)
- , m_bIsDragging(false)
- , m_mode(linkMode)
- , m_nLineIndex(-1)
- {
- // 接收悬停事件,用于显示鼠标切换效果
- setAcceptHoverEvents(true);
- // 设置风格,可选择可拖动
- // setFlag(QGraphicsItem::ItemIsMovable, true);
- setFlag(QGraphicsItem::ItemIsSelectable, true);
- // 接收Item移动消息
- // setFlag(QGraphicsItem::ItemSendsGeometryChanges);
- this->setParentItem(parent);
- m_parentGroup = qgraphicsitem_cast<WindowAppItemLink*>(parent);
- this->setLine(QLineF(ptStart, ptEnd));
- // 设置画笔
- setPen(QPen(COLOR_INF_LINE, PEN_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- }
- /// <summary>
- /// 更新连线位置
- /// </summary>
- /// <param name="ptStart"></param>
- /// <param name="ptEnd"></param>
- void WindowAppItemLinkLine::updateLine(QPointF ptStart, QPointF ptEnd)
- {
- this->setLine(QLineF(ptStart, ptEnd));
- }
- /// <summary>
- /// 更新线段的起点坐标
- /// </summary>
- /// <param name="pt"></param>
- void WindowAppItemLinkLine::setP1(const QPointF pt)
- {
- QLineF ajustLine = this->line();
- ajustLine.setP1(pt);
- this->setLine(ajustLine);
- }
- /// <summary>
- /// 更新线段的终点坐标
- /// </summary>
- /// <param name="pt"></param>
- void WindowAppItemLinkLine::setP2(const QPointF pt)
- {
- QLineF ajustLine = this->line();
- ajustLine.setP2(pt);
- this->setLine(ajustLine);
- }
- /// <summary>
- /// 返回边界区域
- /// </summary>
- /// <returns></returns>
- QRectF WindowAppItemLinkLine::boundingRect() const
- {
- qreal extra = (pen().width()) * 4.0;
- QRectF rc = QRectF(
- line().p1(),
- QSizeF(line().p2().x() - line().p1().x(),
- line().p2().y() - line().p1().y()
- ))
- .normalized()
- .adjusted(-extra, -extra, extra, extra);
- return rc;
- }
- /// <summary>
- /// 形状边界(为了扩大线条的可点击范围)
- /// </summary>
- /// <returns></returns>
- QPainterPath WindowAppItemLinkLine::shape() const
- {
- QPainterPath path = QGraphicsLineItem::shape();
- qreal extra = (pen().width()) * 4.0;
- extra *= 1.414;
- path = QGraphicsLineItem::shape();
- // 通过Stroker设置精确Shape
- QPainterPathStroker stroker;
- stroker.setWidth(extra);
- path = stroker.createStroke(path);
- return path;
- }
- /// <summary>
- /// 绘制线条
- /// </summary>
- /// <param name="painter"></param>
- /// <param name="option"></param>
- /// <param name="widget"></param>
- void WindowAppItemLinkLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget /*= nullptr*/)
- {
- Q_UNUSED(option);
- Q_UNUSED(widget);
- painter->setRenderHint(QPainter::Antialiasing, true);
- painter->save();
- // 如果父类的选中状态发生了变更的话
- if (this->parentItem()->isSelected())
- {
- painter->setPen(QPen(COLOR_INF_LINE, PEN_LINE_WIDTH_SEL, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- }
- else
- {
- painter->setPen(QPen(COLOR_INF_LINE, PEN_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- }
- // 绘制线条
- painter->drawLine(line());
- // 如果是终点连接线,需要绘制箭头
- if (this->m_bLinkEndLine)
- {
- double angle = atan2(line().dy(), -line().dx());
- QPointF arrowP1 = line().p2() + QPointF(sin(angle + M_PI / 3) * LINE_ARROW_SIZE,
- cos(angle + M_PI / 3) * LINE_ARROW_SIZE);
- QPointF arrowP2 = line().p2() + QPointF(sin(angle + M_PI - M_PI / 3) * LINE_ARROW_SIZE,
- cos(angle + M_PI - M_PI / 3) * LINE_ARROW_SIZE);
- painter->drawLine(line().p2(), arrowP1);
- painter->drawLine(line().p2(), arrowP2);
- }
- painter->restore();
- }
- /// <summary>
- /// 跳过Group,自行处理部分消息
- /// </summary>
- /// <param name="event"></param>
- /// <returns></returns>
- bool WindowAppItemLinkLine::sceneEvent(QEvent* event)
- {
- switch (event->type())
- {
- // 处理鼠标Hover消息,很奇怪不知道为什么在Group中无法触发这个消息,只能放到子线段中了
- case QEvent::GraphicsSceneHoverEnter:
- hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent*>(event));
- break;
- case QEvent::GraphicsSceneMousePress:
- mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
- break;
- case QEvent::GraphicsSceneMouseMove:
- mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
- break;
- case QEvent::GraphicsSceneMouseRelease:
- mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
- break;
- }
- event->accept();
- return QGraphicsLineItem::sceneEvent(event);
- }
- ///// <summary>
- ///// 鼠标悬浮事件(用于显示移动用的鼠标)
- ///// </summary>
- ///// <param name="event"></param>
- //void WindowAppItemLinkLine::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
- //{
- // // 如果控件处于选中状态,则根据鼠标位置显示拉伸鼠标
- // if (this->isSelected())
- // {
- // //setCursor(Qt::SizeVerCursor);
- // // setCursor(Qt::SizeHorCursor);
- // }
- //
- // qDebug() << "WindowAppItemLinkLine::hoverMoveEvent";
- //
- // QGraphicsLineItem::hoverMoveEvent(event);
- //}
- //=============================================================================
- //
- // 线条拖动相关代码
- //
- //=============================================================================
- /// <summary>
- /// 鼠标进入悬浮事件(用于显示拖动用的鼠标)
- /// </summary>
- /// <param name="event"></param>
- void WindowAppItemLinkLine::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
- {
- // qDebug() << "WindowAppItemLinkLine::hoverEnterEvent";
- // 如果不支持拖拽,则干脆不能改变鼠标样式
- if (!isSupportDrag())
- {
- return;
- }
- // 根据是水平线还是垂直线显示不同的鼠标
- if (isVertical())
- {
- setCursor(Qt::SizeHorCursor);
- }
- else if(isHorizontal())
- {
- setCursor(Qt::SizeVerCursor);
- }
- // Error
- else
- {
- }
- QGraphicsLineItem::hoverEnterEvent(event);
- }
- /// <summary>
- /// 鼠标按下事件(用于触发Link移动)
- /// </summary>
- /// <param name="event"></param>
- void WindowAppItemLinkLine::mousePressEvent(QGraphicsSceneMouseEvent* event)
- {
- // qDebug() << "WindowAppItemLinkLine::mousePressEvent";
-
- // QPointF mousePoint = event->pos();
- if (!this->isSupportDrag())
- {
- return;
- }
- m_bIsDragging = true;
- QGraphicsLineItem::mousePressEvent(event);
- }
- /// <summary>
- /// 鼠标移动事件(用于移动Link)
- /// </summary>
- /// <param name="event"></param>
- void WindowAppItemLinkLine::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
- {
- // qDebug() << "WindowAppItemLinkLine::mouseMoveEvent";
- QPointF mousePoint = event->pos();
- if (!m_bIsDragging)
- {
- return;
- }
- QPointF lineP1 = this->line().p1();
- QPointF lineP2 = this->line().p2();
- // 水平线移动
- if (isVertical())
- {
- lineP1.setX(mousePoint.x());
- lineP2.setX(mousePoint.x());
- // 交给Group检查一下本次移动是否可行
- if (m_parentGroup->canMove(lineP1, lineP2))
- {
- this->setLine(QLineF(lineP1, lineP2));
- // 发送线段移动信号,用于在Group中同步移动其他线段
- emit lineMoveSignal(this);
- }
- }
- // 垂直线移动
- else if(isHorizontal())
- {
- lineP1.setY(mousePoint.y());
- lineP2.setY(mousePoint.y());
- // 交给Group检查一下本次移动是否可行
- if (m_parentGroup->canMove(lineP1, lineP2))
- {
- this->setLine(QLineF(lineP1, lineP2));
- // 发送线段移动信号,用于在Group中同步移动其他线段
- emit lineMoveSignal(this);
- }
- }
- // Error
- else
- {
- }
- QGraphicsLineItem::mouseMoveEvent(event);
- }
- /// <summary>
- /// 鼠标释放事件(用于鼠标还原以及接收拉伸状态)
- /// </summary>
- /// <param name="event"></param>
- void WindowAppItemLinkLine::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
- {
- // qDebug() << "WindowAppItemLinkLine::mouseReleaseEvent";
- // 还原鼠标
- // setCursor(Qt::ArrowCursor);
- m_bIsDragging = false;
- QGraphicsLineItem::mouseReleaseEvent(event);
- }
- /// <summary>
- /// 是否是垂直线条
- /// </summary>
- /// <returns></returns>
- bool WindowAppItemLinkLine::isVertical()
- {
- QLine seg = this->line().toLine();
- return (seg.x1() == seg.x2());
- }
- /// <summary>
- /// 是否是水平线条
- /// </summary>
- /// <returns></returns>
- bool WindowAppItemLinkLine::isHorizontal()
- {
- QLine seg = this->line().toLine();
- return (seg.y1() == seg.y2());
- }
- /// <summary>
- /// 本线段是否支持拖拽
- /// </summary>
- /// <returns></returns>
- bool WindowAppItemLinkLine::isSupportDrag()
- {
- // 如果终点连线,则不支持拖拽功能
- if (m_bLinkEndLine)
- {
- return false;
- }
- // 如果是普通模式下的起点连线,也不支持拖拽功能
- if (m_bLinkStartLine && m_mode == LINK_MODE::LINK_NORMAL)
- {
- return false;
- }
- return true;
- }
|