QT实现可拖拽表格控件TableWidget

QT实现可拖拽表格控件TableWidget

看到网上很多用上下箭头和按钮来实现TableWidget的拖动排序,我觉得好low,这种操作,我要是客户,我嫌弃。以下给大家介绍:鼠标长按拖拽、插入的TableWidget。

一、需要重写的事件
protected:
    //鼠标事件开启拖拽
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
 
    //拖拽响应事件
    void dragEnterEvent(QDragEnterEvent* event);
    void dragMoveEvent(QDragMoveEvent* event);
    void dropEvent(QDropEvent* event);
二、声明的属性变量
    bool m_validPress;              //在鼠标移动时,判断之前按下时是否是在有效行上
    int m_rowFrom;                  //起始行
    int m_rowTo;                    //目标行
    QString m_dragText;             //item
    QPoint m_dragPoint;             //拖拽起点
三、关键代码的示例
  • 先在mousePressEvent里判断鼠标的操作,比如我这里是左键:

        if (e->button() == Qt::LeftButton)
        {
            QModelIndex index = indexAt(e->pos());
     
            if (index.isValid())
            {
                m_validPress = true;
                m_dragPoint = e->pos();
                m_dragText = this->item(index.row(), 1)->text();
                m_rowFrom = index.row();
            }
        }
     
        QTableWidget::mousePressEvent(e);
  • 接着在mouseMoveEvent里面判断有效性后,开始drag拖动操作:

        if (!m_validPress)
        {
            return;
        }
     
        if (!(e->buttons() & Qt::LeftButton))
        {
            return;
        }
     
        if ((e->pos() - m_dragPoint).manhattanLength() < QApplication::startDragDistance())
        {
            return;
        }
     
        DoDrag(); //拖拽
        m_validPress = false;
  • DoDrag代码,用QMimeData来传递:

        QDrag* drag = new QDrag(this);
        QMimeData* mimeData = new QMimeData;
        mimeData->setText(m_dragText);
        drag->setMimeData(mimeData);
     
        if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
        {
        }
     
        delete drag;

  • dragEnterEvent

        if (e->mimeData()->hasText())
        {
            e->acceptProposedAction();
        }
        else
        {
            e->ignore();
            QTableWidget::dragEnterEvent(e);
        }
  • dragMoveEvent

       if (e->mimeData()->hasText())
       {
           int nCurRow = 0;
           QModelIndex index = indexAt(e->pos());
     
           if (index.isValid())
           {
               if (e->pos().y() - index.row()*rowHeight(m_rowFrom) >= rowHeight(m_rowFrom) / 2)
               {
                   nCurRow = index.row() + 1;
               }
               else
               {
                   nCurRow = index.row();
               }
           }
           else
           {
               if (this->rowCount() >= 1)
               {
                   nCurRow = this->rowCount() - 1;
               }
           }
     
           {
               m_rowTo = nCurRow;
     
               int scrollValue = this->verticalScrollBar()->value();
               int offsetValue = 0;
     
               if (scrollValue > 0 && scrollValue >= this->verticalScrollBar()->maximum())
               {
                   scrollValue = scrollValue - 1;
                   offsetValue = (this->height() - horizontalHeader()->height()) % rowHeight(m_rowFrom) - 3;
               }
               else
               {
                   scrollValue = scrollValue > 0 ? scrollValue - 1 : scrollValue;
               }
           }
     
           e->acceptProposedAction();
           return;
       }
     
       e->ignore();
       QTableWidget::dragMoveEvent(e);
  • dropEvent

    if (this->rowCount() <= 1)
        {
            return;
        }
     
        if (e->mimeData()->hasText())
        {
            if (m_rowTo != m_rowFrom)
            {
                if (this->verticalScrollBar()->value() > 0)
                {
                    //调用你自己的操作,比如我的是更新TableWidget的顺序,发信号给外界
                }
                else
                {
                    //调用你自己的操作,比如我的是更新TableWidget的顺序,发信号给外界
                }
     
                m_rowTo = -1;
                m_rowFrom = -1;
            }
     
            e->acceptProposedAction();
            return;
        }
     
        e->ignore();
        QTableWidget::dropEvent(e);

到这里基本就完成了,我的功能里其实还有显示一条高亮的拖拽提示线,提示当前拖拽数据的落脚点在哪一个位置,这个你们可以自己加在dragMoveEvent里面,在移动的时候更新提示的位置,也可以在鼠标按下的时候就显示,都行。


四、注意点

大多是根据数据的复杂度、还有需求来的,我这里的数据比较复杂,拖拽的影响范围较广,还有很多给外部的信号槽交互,所以很多有很多要注意的地方。

  • 注意对from起始行的有效性判断;
  • 注意在插入的时候,要把from的数据删了,不然你的功能就是复制插入,而不是排序了;
  • 还有注意外界与本控件的信号槽关系,拖拽结束会不会改变selectRow,对应的槽函数处理;
  • 忘了,反正还有几点吧,坑自己踩踩就知道了。

祝大家造出更好的软件。

  • 6
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Qt是一个跨平台的C++应用程序开发框架,提供了丰富的控件和功能,可以用于开发各种类型的应用程序。 在实现表格控件时,如果需要支持多级表头,可以借助Qt的QHeaderView类来实现。QHeaderView类是Qt中用于表格或树型视图的表头控件,它可以显示列或行的标题,并且支持拖动和调整列宽度。 首先,创建一个QTreeView控件作为表格控件的显示部分。然后,创建一个QHeaderView对象作为表格控件的表头,使用setModel()函数将表头设置给表格控件。接下来,设置表头的显示模式为水平模式,使用setSectionResizeMode()函数设置每一列的调整方式,例如,可以设置为可以自动调整大小或者禁止调整大小。 为了支持多级表头,可以使用QHeaderView的addSection()函数来添加多级表头。逐级添加表头时,需要设置每一级表头的标签、起始列、列数和对齐方式。可以使用setHeaderData()函数为每一级的表头设置样式。 接着,使用setHeaderHidden()函数将QTreeView的默认表头隐藏起来,这样就只展示了我们自定义的多级表头。同时,可以使用setRootIsDecorated()函数将树节点的展开和收缩图标隐藏起来,以使得表格控件更加美观。 最后,将数据模型设置给QTreeView控件,通过添加树节点和设置节点的父子关系,来组织表格树的数据结构。数据模型可以继承自QAbstractItemModel类,实现相关的接口函数,以提供数据的展示和操作。 通过以上步骤,我们就可以实现一个支持多级表头的表格控件。用户可以通过拖动和调整表头以调整列宽度,同时展示复杂的表头结构,方便显示和操作大量数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值