Qt鼠标拖动控件交换布局位置

该博客介绍了如何使用Qt实现鼠标拖动时控件交换布局位置的功能,包括重新布局和更新控件内容。通过鼠标按压和释放事件,结合索引定位,实现了控件的拖放操作。同时,还展示了两种实现方式来添加鼠标贴图,使其跟随鼠标移动,提供更直观的拖动视觉效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法很简单,交换鼠标起点控件指针和鼠标落点控件指针的值,然后重新布局

Qt鼠标拖动控件交换布局位置

源文件

#include "widget.h"
#include<QLabel>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    setMinimumSize(1000,800);
    //label = new QLabel(this);
    //label->setFixedSize(80,40);
    //label->hide();
    lay = new QGridLayout(this);
    setLayout(lay);
    lay->setSpacing(0);
    //设置表格布局行列为5*5的形式
    for(int i = 0;i <5 ;++i){
        for(int j = 0;j <5 ;++j)
        {
            qDebug() << i*5+j;
            auto label = new QLabel(QString::number(i*5+j+1));
            label->setAlignment(Qt::AlignCenter);
            label->setFont(QFont("宋体",50));
            label->setStyleSheet("border:2px groove gray");
            lay->addWidget(label,i,j,1,1);
            labels.push_back(label);
        }
    }
}
void Widget::reStartLayout()//重新布局
{
    qDebug() << lay->count();
    for(auto&w : labels){
        lay->removeWidget(w);//移除旧布局
    }
    qDebug() << lay->count();
    for(int i = 0;i <5 ;++i){//生成新布局5*5
        for(int j = 0;j <5 ;++j){
            lay->addWidget(labels[i*5+j],i,j,1,1);
        }
    }
    qDebug() << lay->count();
}
int Widget::indexByPos(const QPoint& pos)
{//根据鼠标pos点取索引
    for(int i = 0;i <5 ;++i){
        for(int j = 0;j <5 ;++j){
            if(lay->cellRect(i, j).contains(pos)){
                qDebug() << i*5+j;
                return i*5+j;//Qlabel*索引
            }
        }
    }
    return -1;
}
void Widget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton){
        pressIndex = indexByPos(event->pos());//拖动起点索引
    }
    QWidget::mousePressEvent(event);
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        if(pressIndex!= -1){
            int index = indexByPos(event->pos());//落点索引
            if(index!= -1 && pressIndex!= index){
                std::swap(labels[pressIndex],labels[index]);//交换起点和落点的QLabel指针
                reStartLayout();
            }
            pressIndex = -1;
        }
    }
    QWidget::mouseReleaseEvent(event);
}

头文件

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void mousePressEvent(QMouseEvent *event) ;
    void mouseReleaseEvent(QMouseEvent *event);
    int indexByPos(const QPoint& pos);
    void reStartLayout();

private:
    QGridLayout* lay;
    std::vector<QLabel*> labels;
    int pressIndex = -1;
    //QPoint move_pos;
    //QLabel* label;
};

下面是只交换控件显示的内容:

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        if(pressIndex!= -1){
            int index = indexByPos(event->pos());//落点索引
            if(index!= -1 && pressIndex!= index){
             QString str1 = labels[pressIndex]->text();
             QString str2 = labels[index]->text();
                  labels[pressIndex]->setText(str2);
                  labels[index]->setText(str1);
            }
        }
    }
    QWidget::mouseReleaseEvent(event);
}

添加鼠标贴图,跟随鼠标移动:
一种实现:重写void paintEvent(QPaintEvent *event);方法

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        if(pressIndex!= -1){
            int index = indexByPos(event->pos());//落点索引
            if(index!= -1 && pressIndex!= index){
                std::swap(labels[pressIndex],labels[index]);//交换起点和落点的QLabel指针
                reStartLayout();
            }
            pressIndex = -1;
            repaint();//立即执行paintEvent方法
        }
    }
    QWidget::mouseReleaseEvent(event);
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{

    if (event->buttons() & Qt::LeftButton) {
        if(pressIndex!= -1){
         move_pos =  event->pos();
         repaint();
        }
    }
    QWidget::mouseReleaseEvent(event);

}

void Widget::paintEvent(QPaintEvent *event)
{
    if(pressIndex!= -1){
        QPainter painter(this);
        QPen pen; //画笔。绘制图形边线,由颜色、宽度、线风格等参数组成
        pen.setColor(QColor(0,0,255));
        painter.setPen(pen);
        painter.setBrush(QColor(79 ,79 ,79));
        painter.setRenderHint(QPainter::Antialiasing);
       // qDebug()<< event->pos().x() <<"y " << event->pos().y();
        painter.drawRect(move_pos.x()-40,move_pos.y(),80,40);
        painter.drawText(move_pos.x(),move_pos.y()+30,QString::number(pressIndex));
    }
}

另一种实现:

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        if(pressIndex!= -1){
            int index = indexByPos(event->pos());//落点索引
            if(index!= -1 && pressIndex!= index){
                std::swap(labels[pressIndex],labels[index]);//交换起点和落点的QLabel指针
                reStartLayout();
            }
            pressIndex = -1;
            if(label->isVisible())
               label->hide();
        }
    }
    QWidget::mouseReleaseEvent(event);
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{

    if (event->buttons() & Qt::LeftButton) {
        if(pressIndex!= -1){
            if(!label->isVisible())
                label->show();
         QPicture p;
         p.setBoundingRect(QRect(event->pos().x()-40,event->pos().y(),80,40));
         QPainter painter(&p);
         painter.setPen(Qt::green);
         painter.setBrush(QColor(79 ,79 ,79));
         painter.drawRect(QRect(event->pos().x()-40,event->pos().y(),80-1,40-1));
         painter.drawText(event->pos().x(),event->pos().y()+30,QString::number(pressIndex));
         label->move(event->pos().x()-40,event->pos().y());
         label->setPicture(p);
        }
    }
    QWidget::mouseReleaseEvent(event);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值