拖动同级别元素显示辅助线,辅助对齐,吸附.

采用jqueryUi      draggable  组件开发。

引用JS  :

  <script src="https://cdn.bootcss.com/jquery/1.11.1/jquery.js"></script>
  <script src="https://cdn.bootcss.com/jqueryui/1.12.1/jquery-ui.js"></script>
  <link href="https://cdn.bootcss.com/jqueryui/1.12.1/jquery-ui.css" rel="stylesheet">
 
css部分:
  body {
    font-family: courier new, courier;
    font-size: 12px;
    padding:0;
    margin:0;
  }
  .draggable_list{
    width:500px;height:500px;background:#ccc;position:relative;left:200px;top:200px;
  }
  .draggable {
    border: 1px solid #ccc;
    display: inline-block;
    cursor: move;
    position: absolute;
  }
  .guide {
    display: none;
    position: absolute;
    left: 0;
    top: 0;
  }
  #guide-h {
    border-top: 1px dashed #55f;
    width: 100%;
  }
  #guide-v {
    border-left: 1px dashed #55f;
    height: 100%;
  }
 
html 部分:
 
<div class="draggable_list">
  <!--需要拖动的div-->
  <div class="draggable">第一个11111111111111div</div>
  <div class="draggable">第二个22div</div>
  <div class="draggable">第三个333333div</div>
  <div class="draggable">第四个ggdgdgdiv</div>
  <div class="draggable">第五个div</div>
  <div class="draggable">第六个div</div>
  <!--拖动辅助线-->
  <div id="guide-h" class="guide"></div>
  <div id="guide-v" class="guide"></div>
</div>
 
JS 部分:
  /**
  * 指标拖动辅助标线
  */
  var MIN_DISTANCE = 8; //捕获的最小距离
  var guides = []; // 没有可用的引导
  var innerOffsetX, innerOffsetY;
  
  $(".draggable").draggable({
    start: function (event, ui) {
      guides = $.map($(".draggable").not(this), computeGuidesForElement);
      //offsetX、offsetY:源元素(srcElement)的X,Y坐标
      innerOffsetX = event.offsetX;
      innerOffsetY = event.offsetY;
    },
    
    /**
    * 参数说明
    * event事件的
    * offsetX:
    * outerwidth: 属性是一个只读的整数,声明了整个窗口的宽度。
    * outerheight: 属性是一个只读的整数,声明了整个窗口的高度。
    */
    
    drag: function (event, ui) {
      //迭代所有的guids,记住最近的h和v guids
      var guideV, guideH, distV = MIN_DISTANCE + 1,
      distH = MIN_DISTANCE + 1,
      offsetV, offsetH;
      var chosenGuides = {
        top: {
          dist: MIN_DISTANCE + 1
        },
        left: {
          dist: MIN_DISTANCE + 1
        }
      };
      var $t = $(this);
      //pageX、pageY:文档坐标x、y ;
      var pos = {
        top: (event.pageY - $('.draggable_list').offset().top) - innerOffsetY ,
        left: (event.pageX - $('.draggable_list').offset().left) - innerOffsetX
      };
      //outerHeight、outerWidth:整个浏览器的高度、宽度
      var w = $t.outerWidth() - 1;
      var h = $t.outerHeight() - 1;
      var elemGuides = computeGuidesForElement(null, pos, w, h);
      $.each(guides, function (i, guide) {
        $.each(elemGuides, function (i, elemGuide) {
          if (guide.type == elemGuide.type) {
            var prop = guide.type == "h" ? "top" : "left";
            var d = Math.abs(elemGuide[prop] - guide[prop]);
            if (d < chosenGuides[prop].dist) {
              chosenGuides[prop].dist = d;
              chosenGuides[prop].offset = elemGuide[prop] - pos[prop];
              chosenGuides[prop].guide = guide;
            }
          }
        });
      });
      if (chosenGuides.top.dist <= MIN_DISTANCE) {
        $("#guide-h").css("top", chosenGuides.top.guide.top).show();
        ui.position.top = chosenGuides.top.guide.top - chosenGuides.top.offset;
      } else {
        $("#guide-h").hide();
        ui.position.top = pos.top;
      }
      if (chosenGuides.left.dist <= MIN_DISTANCE) {
        $("#guide-v").css("left", chosenGuides.left.guide.left).show();
        ui.position.left = chosenGuides.left.guide.left - chosenGuides.left.offset;
      } else {
        $("#guide-v").hide();
        ui.position.left = pos.left;
      }
    },
    stop: function (event, ui) {
      $("#guide-v, #guide-h").hide();
    }
  })
  
  function computeGuidesForElement(elem, pos, w, h) {
    if (elem != null) {
      var $t = $(elem);
      //offset:返回当前元素 的偏移量
      pos = $t.position();
      pos = {
        left: $t.position().left,
        top: $t.position().top
      }
      w = $t.outerWidth() - 1;
      h = $t.outerHeight() - 1;
    }
    return [{
      type: "h",
      left: pos.left,
      top: pos.top
    }, //垂直方向左下对齐线
    {
      type: "h",
      left: pos.left,
      top: pos.top + h
    },
    {
      type: "v",
      left: pos.left,
      top: pos.top
    },
    {
      type: "v",
      left: pos.left + w,
      top: pos.top
    },
    //您可以添加_any_其他指南在这里就好了(如指南10像素单元的左)
    {
      type: "h",
      left: pos.left,
      top: pos.top + h / 2
    },
    {
      type: "v",
      left: pos.left + w / 2,
      top: pos.top
    }];
  }
 
 
 
 
转自   @author sdj
 
 

转载于:https://www.cnblogs.com/loverows/p/7251684.html

<think>好的,用户现在问的是如何在mouseMoveEvent中添加代码,检测与其他控件的对齐位置并绘制辅助线。之前我已经给出了一个基本的拖拽和调整大小的实现,现在用户需要的是更进阶的功能,即对齐辅助线。首先,我需要理解用户的需求。他们可能是在开发一个UI编辑器,希望让用户能够更方便地对齐控件,提升用户体验。 接下来,我得考虑如何实现这个功能。检测对齐位置,通常需要比较当前控件的位置与其他控件的位置,找出边缘或中心对齐的情况。比如,当拖动的按钮的左边与另一个控件的左边在一X坐标时,或者它们的中心Y坐标相,这时候就需要显示垂直或水平的辅助线。 然后,绘制辅助线。在Qt中,绘制通常是在paintEvent里完成的,但用户希望在mouseMoveEvent中处理。这时候可能需要设置一个标志位,当检测到对齐时,记录辅助线的位置,并触发重绘。或者,可以直接在mouseMoveEvent里进行绘制,但需要注意效率问题,避免频繁重绘导致卡顿。 接下来需要考虑如何获取其他控件的位置。主窗口中的容器里可能有多个子控件,遍历这些控件,检查它们的位置与当前拖动控件的位置之间的差异。例如,在CustomButton的mouseMoveEvent中,当拖动时,获取父容器中的所有子控件,排除自己,然后逐个比较位置。 然后,如何处理边缘情况。比如,多个控件可能对齐,需要选择最近的或者所有符合条件的对齐线。另外,辅助线显示可能需要一定的阈值,当位置差在几个像素内时,自动吸附显示线,这样可以提高用户体验,避免频繁出现辅助线。 还有,如何实现自动吸附功能。当用户拖动的控件靠近对齐位置时,自动调整其位置,使其对齐。这需要在检测到对齐时,修改移动的目标坐标,使其对齐到最近的控件边缘或中心。 此外,绘制辅助线的方式。可以使用QPainter在容器控件上绘制,或者在主窗口上绘制。可能需要重写容器控件的paintEvent,检查是否有需要绘制的辅助线,然后进行绘制。需要保存辅助线的位置信息,比如起点和终点,以便在paintEvent中画出。 还需要考虑性能问题。如果有很多控件,频繁遍历和比较可能会影响性能。可以优化,比如只检查可见的控件,或者在拖动开始时缓存其他控件的位置,减少实时计算的开销。 另外,用户可能希望辅助线有不的颜色和样式,比如虚线。这需要在绘制时设置QPen的属性,比如使用Qt::DashLine线型,并选择合适的颜色,如红色或绿色,以便用户明显看到。 最后,测试各种情况,比如多个控件的对齐,不方向的对齐(水平、垂直、中心),以及自动吸附是否正常工作。确保代码的健壮性,避免因为控件位置变化导致的错误。 总结一下,步骤大致是:在mouseMoveEvent中检测与其他控件的位置关系,记录需要显示辅助线位置,然后在paintEvent中绘制这些线。时,可能需要实现自动吸附功能,调整控件的位置到对齐点。这需要处理事件、坐标转换、遍历子控件、绘制图形等多方面的知识,确保各部分协工作,不影响原有拖拽和调整大小的功能。</think>我将为您详细说明在Qt中实现控件对齐辅助线功能的步骤: 一、实现原理 1. 动态检测:在拖动过程中实时检测与其他控件的相对位置 2. 对齐策略:支持左/右/上/下边缘对齐和中心线对齐 3. 视觉反馈:使用红色虚线绘制辅助线,实现自动吸附效果 二、代码实现步骤 1. 在容器组件中添加对齐线存储结构(mainwindow.h) ```cpp class MainWindow : public QMainWindow { // ... protected: void paintEvent(QPaintEvent *event) override; public: QVector<QLine> guideLines; // 存储当前辅助线 // ... }; ``` 2. 修改CustomButton的鼠标移动事件(custombutton.cpp) ```cpp void CustomButton::mouseMoveEvent(QMouseEvent *e) { if (isDragging) { // 获取父容器中所有子控件 QWidget *parent = parentWidget(); QRect currentRect = geometry().translated(pos()); QVector<QLine> lines; QPoint targetPos = e->globalPos() - dragStartPosition; // 检测与其他控件的对齐 foreach(QObject *obj, parent->children()) { if (QWidget *w = qobject_cast<QWidget*>(obj)) { if (w == this) continue; QRect otherRect = w->geometry(); checkAlignment(currentRect, otherRect, targetPos, lines); } } // 更新主窗口的辅助线 if (MainWindow *mw = qobject_cast<MainWindow*>(parent->window())) { mw->guideLines = lines; mw->update(); // 触发重绘 } move(targetPos); } // ...原有代码 } void CustomButton::checkAlignment(QRect &current, QRect &other, QPoint &target, QVector<QLine> &lines) { const int snapMargin = 5; // 自动吸附阈值 // 水平对齐检测 if (qAbs(current.left() - other.left()) < snapMargin) { target.setX(other.left()); lines << QLine(other.left(), 0, other.left(), parentWidget()->height()); } // 垂直对齐检测(类似逻辑) // 中心线检测(补充代码) } ``` 3. 实现辅助线绘制(mainwindow.cpp) ```cpp void MainWindow::paintEvent(QPaintEvent *event) { QMainWindow::paintEvent(event); QPainter painter(this); painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); foreach(QLine line, guideLines) { painter.drawLine(line); } } ``` 三、核心功能说明 1. 对齐检测类型: - 边缘对齐:左($x_1=x_2$)、右($x_1+w_1=x_2+w_2$) - 垂直对齐:上($y_1=y_2$)、下($y_1+h_1=y_2+h_2$) - 中心对齐:水平中心线($y_1+h_1/2 = y_2+h_2/2$) 2. 自动吸附机制: 当控件边缘与其他控件边缘的距离小于$Δ=5px$时: $$ |x_{current} - x_{reference}| < Δ \Rightarrow 自动对齐 $$ 3. 辅助线数学计算: - 水平辅助线方程:$x = C$(常数) - 垂直辅助线方程:$y = C$(常数) 四、性能优化方案 1. 空间分区加速: ```cpp // 使用QHash建立空间索引 QHash<int, QVector<QRect>> spatialHash; ``` 2. 近似检测算法: $$ \text{仅检测可视区域内控件} \quad \text{且} \quad |Δy| < 2h_{current} $$ 3. 延迟绘制: ```cpp // 使用定时器控制刷新频率 QTimer::singleShot(50, this, [this](){ update(); }); ``` 五、扩展功能建议 1. 智能对齐策略: - 最近邻优先原则:$$ \arg\min_{i}(|x_i - x_{current}|) $$ - 多控件对齐:检测多个参考点的复合对齐 2. 辅助线样式配置: ```cpp // 支持不颜色和样式 painter.setPen(QPen(QColor("#FF4081"), 2, Qt::DotLine)); ``` 3. 对齐状态提示: - 显示距离数值:$Δx = x_2 - x_1$ - 播放音效反馈 该实现方案可使控件在拖动时自动显示对齐参考线,并具有自动吸附功能。建议在真实项目中结合QGraphicsView框架实现更高效的可视化编辑系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值