#include "TransparentDraggableCrackObject.h" #include #include #include #include QPointer TransparentDraggableCrackObject::s_activeObject = nullptr; TransparentDraggableCrackObject::TransparentDraggableCrackObject(QCustomPlot *parentPlot, const QString &strUuid, double depth, QString type, QString showNames) : QObject(parentPlot) , mPlot(parentPlot) , m_uuid(strUuid) , m_depth(depth) , m_endX(mPlot->xAxis->range().upper) , mCurve(nullptr) , m_tracer1(nullptr) , m_tracer2(nullptr) , m_dragStateA(IdleA) , m_isAddingLine(false) , m_offsetXB(0.0), m_offsetYB(0.0) , m_dragStateB(IdleB) , m_draggedLineIndex(-1) , m_curveC(nullptr) , m_offsetXC(0.0), m_offsetYC(0.0) , m_cFinished(false) , m_cDragging(false) , m_draggingPoint(false) , m_draggedPointIndex(-1) { if("高导缝" == type) { m_type = TYPE_A; m_lineColor.setNamedColor("#FF0000"); m_typeName = "高导缝"; } else if("高阻缝" == type) { m_type = TYPE_A; m_lineColor.setNamedColor("#400040"); m_typeName = "高阻缝"; } else if("诱导缝" == type) { m_type = TYPE_A; m_lineColor.setNamedColor("#00FFFF"); m_typeName = "诱导缝"; } else if("层理" == type) { m_type = TYPE_A; m_lineColor.setNamedColor("#00FF00"); m_typeName = "层理"; } else if("侵蚀面" == type) { m_type = TYPE_A; m_lineColor.setNamedColor("#409600"); m_typeName = "侵蚀面"; } else if("断层" == type) { m_type = TYPE_A; m_lineColor.setNamedColor("#A65300"); m_typeName = "断层"; } else if("自定义1" == type) { m_type = TYPE_A; m_lineColor.setNamedColor("#000000"); m_typeName = "自定义1"; } else if("自定义2" == type) { m_type = TYPE_A; m_lineColor.setNamedColor("#000000"); m_typeName = "自定义2"; } else if("网状缝" == type) { m_type = TYPE_B; m_lineColor.setNamedColor("#808000"); m_typeName = "网状缝"; } else if("垂直缝" == type) { m_type = TYPE_B; m_lineColor.setNamedColor("#FF0000"); m_typeName = "垂直缝"; } else if("孔洞" == type) { m_type = TYPE_C; m_lineColor.setNamedColor("#FF8064"); m_typeName = "孔洞"; } else if("气孔" == type) { m_type = TYPE_C; m_lineColor.setNamedColor("#FFFF00"); m_typeName = "气孔"; } else if("砾石" == type) { m_type = TYPE_C; m_lineColor.setNamedColor("#000096"); m_typeName = "砾石"; } else if("结核" == type) { m_type = TYPE_C; m_lineColor.setNamedColor("#A65300"); m_typeName = "结核"; } else if("团块" == type) { m_type = TYPE_C; m_lineColor.setNamedColor("#000000"); m_typeName = "团块"; } // 创建的时候判断是否显示 // if(showNames.contains("高导缝")) // { // m_isShow = true; // } // else if(showNames.contains("高阻缝")) // { // m_isShow = true; // } // else if(showNames.contains("诱导缝")) // { // m_isShow = true; // } // else if(showNames.contains("层理")) // { // m_isShow = true; // } // else if(showNames.contains("侵蚀面")) // { // m_isShow = true; // } // else if("断层" == type) // { // m_type = TYPE_A; // m_lineColor.setNamedColor("#A65300"); // } // else if("自定义1" == type) // { // m_type = TYPE_A; // m_lineColor.setNamedColor("#000000"); // } // else if("自定义2" == type) // { // m_type = TYPE_A; // m_lineColor.setNamedColor("#000000"); // } // else if("网状缝" == type) // { // m_type = TYPE_B; // m_lineColor.setNamedColor("#808000"); // } // else if("垂直缝" == type) // { // m_type = TYPE_B; // m_lineColor.setNamedColor("#FF0000"); // } // else if("孔洞" == type) // { // m_type = TYPE_C; // m_lineColor.setNamedColor("#FF8064"); // } // else if("气孔" == type) // { // m_type = TYPE_C; // m_lineColor.setNamedColor("#FFFF00"); // } // else if("砾石" == type) // { // m_type = TYPE_C; // m_lineColor.setNamedColor("#000096"); // } // else if("结核" == type) // { // m_type = TYPE_C; // m_lineColor.setNamedColor("#A65300"); // } // else if("团块" == type) // { // m_type = TYPE_C; // m_lineColor.setNamedColor("#000000"); // } if (m_type == TYPE_A) { m_orig_x1 = m_endX * 0.18; m_orig_x2 = m_endX * 0.82; m_orig_y1 = depth + 1.0; m_orig_y2 = depth - 1.0; m_orig_startX = 0; m_orig_endX = m_endX; m_orig_startDirX = m_endX * 0.3; m_orig_endDirX = m_endX * 0.7; m_offsetXA = 0.0; m_offsetYA = 0.0; mCurve = new QCPItemCurve(mPlot); mCurve->setPen(QPen(m_lineColor, 2)); mCurve->setLayer("overlay"); updateCurveFromTargets(); updateCurvePosition(); auto createTracer = [this](double x, double y) -> QCPItemTracer* { QCPItemTracer *t = new QCPItemTracer(mPlot); t->setStyle(QCPItemTracer::tsSquare); t->setSize(8); t->setPen(QPen(Qt::black, 1)); t->setBrush(QBrush(Qt::black)); t->setSelectable(true); t->setLayer("overlay"); t->position->setCoords(x, y); t->setVisible(false); return t; }; m_tracer1 = createTracer(m_orig_x1 + m_offsetXA, m_orig_y1 + m_offsetYA); m_tracer2 = createTracer(m_orig_x2 + m_offsetXA, m_orig_y2 + m_offsetYA); m_itemText = new QCPItemText(mPlot); m_itemText->setText(m_typeName); m_itemText->setFont(QFont("Arial", 6, QFont::Bold)); m_itemText->setColor(Qt::black); m_itemText->position->setCoords(m_orig_x1 + m_offsetXA + 15, m_orig_y1 + m_offsetYA); m_itemText->setPositionAlignment(Qt::AlignCenter); m_itemText->setLayer("overlay"); m_labelsC.append(m_itemText); updateTracers(); } else if (m_type == TYPE_B) { // nothing } else if (m_type == TYPE_C) { m_curveC = new QCPCurve(mPlot->xAxis, mPlot->yAxis); m_curveC->setPen(QPen(m_lineColor, 2)); m_curveC->setScatterStyle(QCPScatterStyle::ssCircle); m_curveC->setLineStyle(QCPCurve::lsLine); m_curveC->setLayer("overlay"); } mPlot->installEventFilter(this); mPlot->replot(); } TransparentDraggableCrackObject::~TransparentDraggableCrackObject() { if (m_type == TYPE_B) clearLines(); if (m_type == TYPE_C) clearPolylineC(); if (s_activeObject == this) s_activeObject = nullptr; } void TransparentDraggableCrackObject::isShow(bool is) { this->m_isShow = is; if(this->mCurve) { this->mCurve->setVisible(this->m_isShow); } if(this->m_curveC) { this->m_curveC->setVisible(this->m_isShow); } for (const LineItem &item : m_lines) { if (item.line) { item.line->setVisible(this->m_isShow); } } this->mPlot->replot(); } // ========== 模式A辅助 ========== void TransparentDraggableCrackObject::updateCurveFromTargets() { double t1 = m_orig_x1 / m_endX; double t2 = m_orig_x2 / m_endX; double u1 = 1 - t1, u2 = 1 - t2; double P0x = 0, P0y = m_depth; double P3x = m_endX, P3y = m_depth; double P1x = m_orig_x1, P2x = m_orig_x2; double a11 = 3 * u1 * u1 * t1; double a12 = 3 * u1 * t1 * t1; double b1 = m_orig_y1 - (u1*u1*u1 * P0y + t1*t1*t1 * P3y); double a21 = 3 * u2 * u2 * t2; double a22 = 3 * u2 * t2 * t2; double b2 = m_orig_y2 - (u2*u2*u2 * P0y + t2*t2*t2 * P3y); double det = a11 * a22 - a12 * a21; if (fabs(det) > 1e-6) { double P1y = (b1 * a22 - a12 * b2) / det; double P2y = (a11 * b2 - b1 * a21) / det; m_orig_startDirX = P1x; m_orig_startDirY = P1y; m_orig_endDirX = P2x; m_orig_endDirY = P2y; } } void TransparentDraggableCrackObject::updateCurvePosition() { if (!mCurve) return; mCurve->start->setCoords(m_orig_startX + m_offsetXA, m_depth + m_offsetYA); mCurve->end->setCoords(m_orig_endX + m_offsetXA, m_depth + m_offsetYA); mCurve->startDir->setCoords(m_orig_startDirX + m_offsetXA, m_orig_startDirY + m_offsetYA); mCurve->endDir->setCoords(m_orig_endDirX + m_offsetXA, m_orig_endDirY + m_offsetYA); } void TransparentDraggableCrackObject::updateTracers() { if (!m_tracer1 || !m_tracer2) return; m_tracer1->position->setCoords(m_orig_x1 + m_offsetXA, m_orig_y1 + m_offsetYA); m_tracer2->position->setCoords(m_orig_x2 + m_offsetXA, m_orig_y2 + m_offsetYA); m_itemText->position->setCoords(m_orig_x1 + m_offsetXA + 15, m_orig_y1 + m_offsetYA); } void TransparentDraggableCrackObject::setTracerHighlight(QCPItemTracer *tracer, bool highlight) { if (!tracer) return; if (highlight) { tracer->setPen(QPen(Qt::red, 2)); tracer->setBrush(QBrush(Qt::red)); } else { tracer->setPen(QPen(Qt::black, 1)); tracer->setBrush(QBrush(Qt::black)); m_tracer1->setVisible(true); m_tracer2->setVisible(true); } mPlot->replot(); } // ========== 模式B辅助 ========== void TransparentDraggableCrackObject::updateLineEndpoints(LineItem &item) { item.startTracer->position->setCoords(item.startOrig.x() + m_offsetXB, item.startOrig.y() + m_offsetYB); item.endTracer->position->setCoords(item.endOrig.x() + m_offsetXB, item.endOrig.y() + m_offsetYB); } void TransparentDraggableCrackObject::updateLinesPosition() { for (auto &item : m_lines) { item.line->start->setCoords(item.startOrig.x() + m_offsetXB, item.startOrig.y() + m_offsetYB); item.line->end->setCoords(item.endOrig.x() + m_offsetXB, item.endOrig.y() + m_offsetYB); updateLineEndpoints(item); } } void TransparentDraggableCrackObject::clearLines() { for (auto &item : m_lines) { mPlot->removeItem(item.line); delete item.line; if (item.startTracer) { mPlot->removeItem(item.startTracer); delete item.startTracer; } if (item.endTracer) { mPlot->removeItem(item.endTracer); delete item.endTracer; } } m_lines.clear(); m_isAddingLine = false; mPlot->replot(); } // ========== 模式C辅助 ========== void TransparentDraggableCrackObject::updatePolylineC(bool closed) { if (!m_curveC) return; if (m_pointsC.isEmpty()) { m_curveC->setData(QVector(), QVector()); return; } QVector xs, ys; for (const auto &p : m_pointsC) { xs << p.x() + m_offsetXC; ys << p.y() + m_offsetYC; } if (closed && m_pointsC.size() >= 3) { xs << m_pointsC.first().x() + m_offsetXC; ys << m_pointsC.first().y() + m_offsetYC; } m_curveC->setData(xs, ys); } void TransparentDraggableCrackObject::clearPolylineC() { for (QCPItemText* label : m_labelsC) { if (label) { // 断开与 mPlot 的父子关系,防止 mPlot 销毁时自动删除 label->setParent(nullptr); delete label; } } m_labelsC.clear(); m_pointsC.clear(); if (m_curveC) { m_curveC->setData(QVector(), QVector()); } m_offsetXC = m_offsetYC = 0.0; m_cFinished = false; m_draggingPoint = false; m_draggedPointIndex = -1; if (s_activeObject == this) s_activeObject = nullptr; mPlot->replot(); } // ========== 状态重置 ========== void TransparentDraggableCrackObject::deactivate() { qDebug() << "[Deactivate]" << m_uuid; if (m_type == TYPE_A) { setTracerHighlight(m_tracer1, false); setTracerHighlight(m_tracer2, false); m_dragStateA = IdleA; m_tracer1->setVisible(false); m_tracer2->setVisible(false); } else if (m_type == TYPE_B) { m_dragStateB = IdleB; m_draggedLineIndex = -1; } else if (m_type == TYPE_C) { m_cDragging = false; m_draggingPoint = false; m_draggedPointIndex = -1; } mPlot->replot(); } // ========== 事件过滤器 ========== bool TransparentDraggableCrackObject::eventFilter(QObject *obj, QEvent *event) { if (obj != mPlot) return false; if (event->type() == QEvent::Wheel) return false; QMouseEvent *me = static_cast(event); bool shiftPressed = (me->modifiers() & Qt::ShiftModifier); // 鼠标按下 if (event->type() == QEvent::MouseButtonPress && me->button() == Qt::LeftButton) { bool hit = false; // ========== 模式B:添加直线(优先级最高) ========== if (m_type == TYPE_B && shiftPressed) { if (!m_isAddingLine) { double x = mPlot->xAxis->pixelToCoord(me->pos().x()); double y = mPlot->yAxis->pixelToCoord(me->pos().y()); m_tempPoint = QPointF(x - m_offsetXB, y - m_offsetYB); m_isAddingLine = true; qDebug() << "Start adding line, point:" << m_tempPoint; event->accept(); return true; } else { double x = mPlot->xAxis->pixelToCoord(me->pos().x()); double y = mPlot->yAxis->pixelToCoord(me->pos().y()); QPointF p2(x - m_offsetXB, y - m_offsetYB); QCPItemLine *line = new QCPItemLine(mPlot); line->setPen(QPen(m_lineColor, 2)); line->setLayer("overlay"); auto createTracer = [this](double x, double y, const QColor &color) -> QCPItemTracer* { QCPItemTracer *t = new QCPItemTracer(mPlot); t->setStyle(QCPItemTracer::tsSquare); t->setSize(10); t->setPen(QPen(Qt::black, 1)); t->setBrush(QBrush(color)); t->setSelectable(true); t->setLayer("overlay"); t->position->setCoords(x + m_offsetXB, y + m_offsetYB); return t; }; QCPItemTracer *startTracer = createTracer(m_tempPoint.x(), m_tempPoint.y(), Qt::black); QCPItemTracer *endTracer = createTracer(p2.x(), p2.y(), Qt::black); LineItem item; item.startOrig = m_tempPoint; item.endOrig = p2; item.line = line; item.startTracer = startTracer; item.endTracer = endTracer; m_lines.append(item); updateLinesPosition(); m_isAddingLine = false; mPlot->replot(); qDebug() << "Line added from" << m_tempPoint << "to" << p2; event->accept(); return true; } } // ========== 模式A ========== if (m_type == TYPE_A && !shiftPressed) { QPointF pixel = me->localPos(); double d1 = m_tracer1->selectTest(pixel, false); double d2 = m_tracer2->selectTest(pixel, false); double curveDist = mCurve->selectTest(pixel, false); if (d1 >= 0 && d1 < 15 || d2 >= 0 && d2 < 15 || (curveDist >= 0 && curveDist < 5)) { hit = true; if (s_activeObject && s_activeObject != this) { s_activeObject->deactivate(); } s_activeObject = this; if (d1 >= 0 && d1 < 15) { m_dragStateA = DraggingPoint1; setTracerHighlight(m_tracer1, true); } else if (d2 >= 0 && d2 < 15) { m_dragStateA = DraggingPoint2; setTracerHighlight(m_tracer2, true); } else { m_dragStateA = DraggingCurveA; m_lastDragPixelA = pixel; } event->accept(); return true; } } // ========== 模式B:拖拽(非Shift) ========== if (m_type == TYPE_B && !shiftPressed && !m_isAddingLine) { QPointF pixel = me->localPos(); bool found = false; for (int i = 0; i < m_lines.size(); ++i) { auto &item = m_lines[i]; if (item.startTracer->selectTest(pixel, false) >= 0 && item.startTracer->selectTest(pixel, false) < 10) { found = true; hit = true; if (s_activeObject && s_activeObject != this) s_activeObject->deactivate(); s_activeObject = this; m_dragStateB = DraggingStartPoint; m_draggedLineIndex = i; m_bDragStart = pixel; event->accept(); return true; } if (item.endTracer->selectTest(pixel, false) >= 0 && item.endTracer->selectTest(pixel, false) < 10) { found = true; hit = true; if (s_activeObject && s_activeObject != this) s_activeObject->deactivate(); s_activeObject = this; m_dragStateB = DraggingEndPoint; m_draggedLineIndex = i; m_bDragStart = pixel; event->accept(); return true; } } if (!found) { for (int i = 0; i < m_lines.size(); ++i) { double dist = m_lines[i].line->selectTest(pixel, false); if (dist >= 0 && dist < 3) { hit = true; if (s_activeObject && s_activeObject != this) s_activeObject->deactivate(); s_activeObject = this; m_dragStateB = DraggingLineOverall; m_bDragStart = pixel; event->accept(); return true; } } } } // ========== 模式C ========== if (m_type == TYPE_C) { // 1. 左键添加点(Shift) if (shiftPressed && me->button() == Qt::LeftButton && !m_cFinished) { if (s_activeObject != this) { if (s_activeObject) s_activeObject->deactivate(); s_activeObject = this; } double x = mPlot->xAxis->pixelToCoord(me->pos().x()); double y = mPlot->yAxis->pixelToCoord(me->pos().y()); QPointF pt(x - m_offsetXC, y - m_offsetYC); m_pointsC.append(pt); QCPItemText *label = new QCPItemText(mPlot); label->setText(" "); label->setFont(QFont("Arial", 6, QFont::Bold)); label->setColor(Qt::black); label->setBrush(QBrush(Qt::black)); label->setPen(QPen(Qt::black, 1)); label->position->setCoords(x, y); label->setPositionAlignment(Qt::AlignCenter); label->setLayer("overlay"); m_labelsC.append(label); updatePolylineC(false); mPlot->replot(); event->accept(); return true; } // 2. 左键空白闭环(非Shift,未完成时) if (!shiftPressed && me->button() == Qt::LeftButton && !m_cFinished) { if (m_pointsC.size() >= 3) { m_cFinished = true; updatePolylineC(true); mPlot->replot(); } else { clearPolylineC(); } if (s_activeObject == this) { s_activeObject->deactivate(); s_activeObject = nullptr; } event->accept(); return true; } // 3. 拖拽整体或点(已完成,非Shift左键) if (!shiftPressed && me->button() == Qt::LeftButton && m_cFinished) { QPointF pixel = me->localPos(); // 优先检测是否命中某个数据点(通过标签) int hitPointIndex = -1; for (int i = 0; i < m_labelsC.size(); ++i) { double dist = m_labelsC[i]->selectTest(pixel, false); if (dist >= 0 && dist < 10) { hitPointIndex = i; break; } } if (hitPointIndex >= 0) { hit = true; if (s_activeObject != this) { if (s_activeObject) s_activeObject->deactivate(); s_activeObject = this; } m_draggingPoint = true; m_draggedPointIndex = hitPointIndex; // 记录拖拽开始时的鼠标像素坐标和点的原始坐标(用于计算偏移) m_cDragStart = pixel; event->accept(); return true; } else { // 未命中点,检测曲线本体 double curveDist = m_curveC ? m_curveC->selectTest(pixel, false) : -1; if (curveDist >= 0 && curveDist < 3) { hit = true; if (s_activeObject != this) { if (s_activeObject) s_activeObject->deactivate(); s_activeObject = this; } m_cDragging = true; m_cDragStart = pixel; event->accept(); return true; } else { // 未命中任何图元,清除活动对象 if (s_activeObject == this) { s_activeObject->deactivate(); s_activeObject = nullptr; } return false; } } } } // 未命中任何图元:清除全局活动对象 if (!hit) { if (s_activeObject) { s_activeObject->deactivate(); s_activeObject = nullptr; } return false; } return false; } // 鼠标移动 if (event->type() == QEvent::MouseMove) { if (s_activeObject != this) return false; // 模式A移动 if (m_type == TYPE_A) { if (m_dragStateA == DraggingPoint1 || m_dragStateA == DraggingPoint2) { double newY = mPlot->yAxis->pixelToCoord(me->localPos().y()); double currentY = (m_dragStateA == DraggingPoint1) ? m_orig_y1 : m_orig_y2; double deltaY = newY - (currentY + m_offsetYA); if (fabs(deltaY) > 5) deltaY = (deltaY > 0 ? 5 : -5); double newOrigY = currentY + deltaY; double minY = m_depth - 100; double maxY = m_depth + 100; newOrigY = qBound(minY, newOrigY, maxY); if (m_dragStateA == DraggingPoint1) m_orig_y1 = newOrigY; else m_orig_y2 = newOrigY; updateCurveFromTargets(); updateCurvePosition(); updateTracers(); mPlot->replot(); return true; } else if (m_dragStateA == DraggingCurveA) { QPointF current = me->localPos(); double oldX = mPlot->xAxis->pixelToCoord(m_lastDragPixelA.x()); double newX = mPlot->xAxis->pixelToCoord(current.x()); double oldY = mPlot->yAxis->pixelToCoord(m_lastDragPixelA.y()); double newY = mPlot->yAxis->pixelToCoord(current.y()); double dx = newX - oldX; double dy = newY - oldY; m_offsetXA += dx; m_offsetYA += dy; updateCurvePosition(); updateTracers(); mPlot->replot(); m_lastDragPixelA = current; return true; } } // 模式B移动 else if (m_type == TYPE_B && m_dragStateB != IdleB) { QPointF current = me->localPos(); double oldX = mPlot->xAxis->pixelToCoord(m_bDragStart.x()); double newX = mPlot->xAxis->pixelToCoord(current.x()); double oldY = mPlot->yAxis->pixelToCoord(m_bDragStart.y()); double newY = mPlot->yAxis->pixelToCoord(current.y()); double dx = newX - oldX; double dy = newY - oldY; if (m_dragStateB == DraggingLineOverall) { m_offsetXB += dx; m_offsetYB += dy; updateLinesPosition(); } else if (m_dragStateB == DraggingStartPoint || m_dragStateB == DraggingEndPoint) { int idx = m_draggedLineIndex; if (idx >= 0 && idx < m_lines.size()) { LineItem &item = m_lines[idx]; if (m_dragStateB == DraggingStartPoint) { item.startOrig.rx() += dx; item.startOrig.ry() += dy; } else { item.endOrig.rx() += dx; item.endOrig.ry() += dy; } item.line->start->setCoords(item.startOrig.x() + m_offsetXB, item.startOrig.y() + m_offsetYB); item.line->end->setCoords(item.endOrig.x() + m_offsetXB, item.endOrig.y() + m_offsetYB); updateLineEndpoints(item); } } mPlot->replot(); m_bDragStart = current; return true; } // 模式C移动 // 模式C移动 else if (m_type == TYPE_C) { if (m_cDragging) { // 整体拖拽 QPointF current = me->localPos(); double oldX = mPlot->xAxis->pixelToCoord(m_cDragStart.x()); double newX = mPlot->xAxis->pixelToCoord(current.x()); double oldY = mPlot->yAxis->pixelToCoord(m_cDragStart.y()); double newY = mPlot->yAxis->pixelToCoord(current.y()); double dx = newX - oldX; double dy = newY - oldY; m_offsetXC += dx; m_offsetYC += dy; for (int i = 0; i < m_pointsC.size(); ++i) { m_labelsC[i]->position->setCoords(m_pointsC[i].x() + m_offsetXC, m_pointsC[i].y() + m_offsetYC); } updatePolylineC(m_cFinished && m_pointsC.size() >= 3); mPlot->replot(); m_cDragStart = current; return true; } else if (m_draggingPoint) { // 点拖拽:支持二维移动 QPointF current = me->localPos(); // 计算鼠标在轴坐标系下的移动量(直接使用像素转坐标,但为了精确,计算差值) double oldX = mPlot->xAxis->pixelToCoord(m_cDragStart.x()); double newX = mPlot->xAxis->pixelToCoord(current.x()); double oldY = mPlot->yAxis->pixelToCoord(m_cDragStart.y()); double newY = mPlot->yAxis->pixelToCoord(current.y()); double dx = newX - oldX; double dy = newY - oldY; // 更新点的原始坐标 m_pointsC[m_draggedPointIndex].rx() += dx; m_pointsC[m_draggedPointIndex].ry() += dy; // 更新标签位置 m_labelsC[m_draggedPointIndex]->position->setCoords(m_pointsC[m_draggedPointIndex].x() + m_offsetXC, m_pointsC[m_draggedPointIndex].y() + m_offsetYC); updatePolylineC(m_cFinished && m_pointsC.size() >= 3); mPlot->replot(); // 更新拖拽起始点 m_cDragStart = current; return true; } } return false; } // 鼠标释放 if (event->type() == QEvent::MouseButtonRelease && me->button() == Qt::LeftButton) { if (s_activeObject != this) return false; if (m_type == TYPE_A && m_dragStateA != IdleA) { setTracerHighlight(m_tracer1, false); setTracerHighlight(m_tracer2, false); m_dragStateA = IdleA; return true; } else if (m_type == TYPE_B && m_dragStateB != IdleB) { m_dragStateB = IdleB; m_draggedLineIndex = -1; return true; } else if (m_type == TYPE_C) { if (m_cDragging) { m_cDragging = false; return true; } else if (m_draggingPoint) { m_draggingPoint = false; m_draggedPointIndex = -1; return true; } } } return false; }