Qt 拖动控件时使其自动对齐

演示及其理论

演示:

理论:首先获取父窗口下所有子窗口,然后拖动控件去检测,检测成功后使用画家类绘制辅助线。

1、拖动控件

        拖动控件需要满足以下条件:鼠标点击处有控件,鼠标位置的偏移。


/
void MyPushButton::mousePressEvent(QMouseEvent *e)
{
    
    if(e->button()==Qt::LeftButton){
        QPoint mousePos = e->pos();
        IsMousePress=true;
        QWidget * scele = childAt(mousePos);//获取鼠标点击位置的控件
        lastMousePos=e->globalPos();//获取全局位置
    }
    QWidget::mousePressEvent(e);
}

void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
    if(e->button()==Qt::LeftButton){
        IsMousePress=false;
    }
    QWidget::mouseReleaseEvent(e);
}

void MyPushButton::mouseMoveEvent(QMouseEvent *e)
{
    if(IsMousePress&&你的控件!=null){
        QPoint delta=e->globalPos()-lastMousePos;//鼠标位置差值,没有这个会让控件原点为鼠标坐标
        你的控件->move(pos()+delta);//移动代码
        lastMousePos=e->globalPos();//重置
    }
    QWidget::mouseMoveEvent(e);//消息传递
}

很简单的移动。

2、控件对齐

        首先获取控件父对象的所有子控件,很绕吧,因为有的时候我不知道这个控件的父对象是谁时用的上。

    QList<QWidget *> childWidgets;//全局变量

    childWidgets=findChildren<QWidget *>();//这个是在知晓其父对象时可以使用

    childWidgets= 你的控件->parentWidget()->findChildren<QWidget *>();//不知道父窗口的情况

        随后,需要一个判定条件,当鼠标拖着控件靠近另一个控件时控件就会吸附上去,但是很难分开。这个时候就需要一个判定条件,在鼠标点击事件中获取鼠标相对于控件的距离。

    //全局变量
    int last_mouse_pos_x;
    int last_mouse_pos_y;

    //鼠标按下事件中记录当前鼠标的位置相对与控件的距离
    last_mouse_pos_x=e->x()-scele_widget->geometry().left();
    last_mouse_pos_y=e->y()-scele_widget->geometry().top();

        现在所需的所有变量都有了,就可以开始了!

void Desginer::mouseMoveEvent(QMouseEvent *e)
{
    if (e->buttons() & Qt::LeftButton) {;

        // 如果有拖动的控件
        if (scele_widget) {
            //qDebug()<<last_mouse_pos;
            foreach(QWidget * sele,childWidgets){
                if(sele!=scele_widget){//排除与自己检测
                    int x_distance = scele_widget->geometry().left() - sele->geometry().left();//与另一个控件的距离检测
                    int y_distance=scele_widget->geometry().top()-sele->geometry().top();
                    int c_distance=scele_widget->geometry().center().x()-sele->geometry().center().x();
                    if(qAbs(x_distance)<10 &&qAbs(qAbs(e->x()-scele_widget->geometry().left())-last_mouse_pos_x)<=10 ){//当距离小于10,鼠标当前与控件的相对距离减去按下时的距离小于时才会执行对齐
                        isleft=true;//用于绘制辅助线
                        scele_widget->move(sele->x(),scele_widget->y());//x轴对齐

                    }
                    else if (qAbs(x_distance)>10){
                        isleft=false;
                    }

                    if(qAbs(y_distance)<10&&qAbs(qAbs(e->y()-scele_widget->geometry().top())-last_mouse_pos_y)<=10){
                      
                        istop=true;
                        scele_widget->move(scele_widget->x(),sele->y());//y轴对齐
                    }
                    else if(qAbs(y_distance)>10){
                        istop=false;
                    }

                    if(qAbs(c_distance)<10&&qAbs(qAbs(e->x()-scele_widget->geometry().left())-last_mouse_pos_x)<=10){
                        iscenter=true;
                        scele_widget->move(sele->geometry().center().x()-scele_widget->width()/2,scele_widget->y());//中心对齐
                    }
                    else{
                        iscenter=false;
                    }
                }
                if(qAbs(qAbs(e->x()-scele_widget->geometry().left())-last_mouse_pos_x)>15){

                    //这里是在鼠标相对位置改变后重置其相对位置以便于下次检测        
                    last_mouse_pos_x=e->x()-scele_widget->geometry().left();
                }
                else if(qAbs(qAbs(e->y()-scele_widget->geometry().top())-last_mouse_pos_y)>15){
                    last_mouse_pos_y=e->y()-scele_widget->geometry().top();
                }

            }
        }
    }
    QWidget::mouseMoveEvent(e);//这句是将事件传递给上层,没有这个的的话顶层窗口接收不到
}

3、画辅助线

void Desginer::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QSize widgetsize=this->size();
    painter.drawRect(0,0,widgetsize.width()-1,widgetsize.height()-1);
    QPen pen;
    pen.setStyle(Qt::DashLine);
    painter.setPen(pen);
    if(isleft&&scele_widget!=NULL){
        painter.drawLine(scele_widget->x()-1,0,scele_widget->x()-1,this->height());
        update();//刷新
        //qDebug()<<"x轴对齐"<<isleft;
    }
    else{
        update();
    }
    if(istop&&scele_widget!=NULL){
        painter.drawLine(0,scele_widget->y()-1,this->width(),scele_widget->y()-1);
        update();
        //qDebug()<<"y轴对齐"<<istop;
    }
    else{
        update();
    }

    if(iscenter&&scele_widget!=NULL){
        painter.drawLine(scele_widget->geometry().center().x(),0,scele_widget->geometry().center().x(),this->width());
        update();
    }
    else{
        update();
    }


}

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值