Qt 实现动态调整流程指令顺序(通过鼠标事件实现)

// 事件
bool CTestCfgWidget::eventFilter(QObject *, QEvent *evt)
{
    //获取鼠标坐标和窗口坐标
    static QPoint lastPnt;
    static bool isHover = false;
    static bool ismove = false;
    // 鼠标按下
    if (evt->type() == QEvent::MouseButtonPress)
    {
         QMouseEvent* e = static_cast<QMouseEvent*>(evt);
        //得到水平布局的数量,循环判断鼠标在一个水平布局中
        int layoutcount = m_processcfg_mainlayout->count();
        for (int k=0;k<layoutcount;k++)
        {
            QHBoxLayout *hlayout = static_cast<QHBoxLayout *>(m_processcfg_mainlayout->itemAt(k));
            if (!hlayout)
            {
                return true;
            }
            QRect rect = hlayout->geometry();
            //is the mouse is clicking the key and //if the mouse click the right key
            if (rect.contains(e->pos()) && (e->button() == Qt::LeftButton)) 
            {
                lastPnt = e->pos();
                isHover = true;
                //得到要移动的layout编号
                m_layoutno = k;
                break;
            }

        }
        
         
    }
    // 鼠标移动
    else if (evt->type() == QEvent::MouseMove && isHover)
     {
        ismove = true;
         // 鼠标位置
         QMouseEvent* e = static_cast<QMouseEvent*>(evt);
        int dx = e->pos().x() - lastPnt.x();
        int dy = e->pos().y() - lastPnt.y();
        lastPnt = e->pos();
         
        // 修改对象位置
        m_label[m_layoutno]->move(m_label[m_layoutno]->x(), m_label[m_layoutno]->y() + dy);
        m_vec_process_cmdcombox[m_layoutno]->move(m_vec_process_cmdcombox[m_layoutno]->x(), m_vec_process_cmdcombox[m_layoutno]->y() + dy);
        m_vec_process_devicecombox[m_layoutno]->move(m_vec_process_devicecombox[m_layoutno]->x(), m_vec_process_devicecombox[m_layoutno]->y() + dy);
        m_isautocombox[m_layoutno]->move(m_isautocombox[m_layoutno]->x(), m_isautocombox[m_layoutno]->y() + dy);
        m_vec_isdelete_processcfg_checkbox[m_layoutno]->move(m_vec_isdelete_processcfg_checkbox[m_layoutno]->x(), m_vec_isdelete_processcfg_checkbox[m_layoutno]->y() + dy);
        //qDebug() << "m_layoutno:" << m_layoutno << endl;
        if (m_firstmove)
        {
            QLayoutItem *item = m_processcfg_mainlayout->itemAt(m_layoutno);
            m_processcfg_mainlayout->removeItem(item);
            delete item;
            qDebug() << "MOVE" << endl;
            m_firstmove = false;
        }
    }
    else if (evt->type() == QEvent::MouseButtonRelease && isHover &&ismove)
    {
        //插入布局,获得鼠标松开左键的坐标值,判断鼠标此时在哪一个布局内,在它之前插入布局
        QMouseEvent* e = static_cast<QMouseEvent*>(evt);
        int LayoutIndex = 0;

        //插入移动的布局
        QHBoxLayout *layout = new QHBoxLayout;
        layout->addWidget(m_label[m_layoutno]);
        layout->addWidget(m_vec_process_cmdcombox[m_layoutno]);
        layout->addWidget(m_vec_process_devicecombox[m_layoutno]);
        layout->addWidget(m_isautocombox[m_layoutno]);
        layout->addWidget(m_vec_isdelete_processcfg_checkbox[m_layoutno]);

        //如何获得布局index?可以通过算术来得到
        int layoutcount = m_processcfg_mainlayout->count();
        //qDebug() << "layoutcount:" << layoutcount << endl;
        for (int k = 0; k < layoutcount; k++)
        {
            QHBoxLayout *hlayout = static_cast<QHBoxLayout *>(m_processcfg_mainlayout->itemAt(k));
            if (!hlayout)
            {
                return true;
            }
            QRect rect = hlayout->geometry();
            QHBoxLayout *hlayout1 = static_cast<QHBoxLayout *>(m_processcfg_mainlayout->itemAt(k+1));
            //在移动到最下方的时候,因为在鼠标移动的时候已经删除布局
            if (!hlayout1 && k == layoutcount-1)
            {
                LayoutIndex = k;
                break;
            }
            QRect rect1 = hlayout1->geometry();
            if (e->pos().x()>rect.x() && (e->pos().y() > rect.y() && e->pos().y() < rect1.y() ) )
            {
                LayoutIndex = k;
                break;
            }

            if (k==0 && e->pos().y()>0 && e->pos().y()<rect.y() )
            {
                LayoutIndex = -1;
                break;
            }

        }
        m_processcfg_mainlayout->insertLayout(LayoutIndex+1, layout);

        QLabel *label = m_label[m_layoutno];
        m_label.remove(m_layoutno);
        if (LayoutIndex == m_label.size())
        {
            m_label.push_back(label);
        }
        else
        {
            m_label.insert(LayoutIndex + 1, label);
        }

        qDebug() << "TEST1 ==============================================" << endl;
        

        QComboBox *cmd = m_vec_process_cmdcombox[m_layoutno];
        m_vec_process_cmdcombox.remove(m_layoutno);
        if (m_vec_process_cmdcombox.size() == LayoutIndex)
        {
            m_vec_process_cmdcombox.push_back(cmd);
        }
        else
        {
            m_vec_process_cmdcombox.insert(LayoutIndex + 1, cmd);
        }

        QComboBox *device = m_vec_process_devicecombox[m_layoutno];
        m_vec_process_devicecombox.remove(m_layoutno);
        if (m_vec_process_devicecombox.size() == LayoutIndex)
        {
            m_vec_process_devicecombox.push_back(device);
        }
        else
        {
            m_vec_process_devicecombox.insert(LayoutIndex + 1, device);
        }
        

        qDebug() << "TEST2 ==============================================" << endl;

        QComboBox *isauto = m_isautocombox[m_layoutno];
        m_isautocombox.remove(m_layoutno);
        if (m_isautocombox.size() == LayoutIndex)
        {
            m_isautocombox.push_back(isauto);
        }
        else
        {
            m_isautocombox.insert(LayoutIndex + 1, isauto);
        }
        


        QCheckBox *removecheck = m_vec_isdelete_processcfg_checkbox[m_layoutno];
        m_vec_isdelete_processcfg_checkbox.remove(m_layoutno);
        if (m_vec_isdelete_processcfg_checkbox.size() == LayoutIndex)
        {
            m_vec_isdelete_processcfg_checkbox.push_back(removecheck);
        }
        else
        {
            m_vec_isdelete_processcfg_checkbox.insert(LayoutIndex + 1, removecheck);
        }

        qDebug() << "TEST3 ==============================================" << endl;


        //重置label的编号
        int size = m_label.size();
        for (int i=0;i<size;i++)
        {
            QString number = QString::number(i + 1, 10);
            m_label[i]->setText(number);
        }


        int testcount = m_processcfg_mainlayout->count();

        //qDebug() << "testcount:" << testcount << endl;

        //删除正在移动的布局

        //计算index的值
        int index = -1;
        //1 获得鼠标点击左键的坐标值,2 获得label编号,循环判断鼠标此时在哪一个水平布局内,3 得到index,删除该水平布局

        //如果选中,删除该行的控件

        testcount = m_processcfg_mainlayout->count();
        
        m_processcfg_widget->setLayout(m_processcfg_mainlayout);
        ui.ProcessCfgscrollArea->setWidget(m_processcfg_widget);

    
        isHover = false;

        m_firstmove = true;

        ismove = false;
    }
    return false;
}

在所需页面调用installEventFilter函数,如下:

m_processcfg_widget->installEventFilter(this);

原文地址:https://www.cnblogs.com/LuckCoder/p/10895645.html