拖动结束时未调用 QTableView mouseRelease 事件,错误?

Posted

技术标签:

【中文标题】拖动结束时未调用 QTableView mouseRelease 事件,错误?【英文标题】:QTableView mouseRelease event not called when drag ends, bug? 【发布时间】:2012-01-31 16:39:51 【问题描述】:

我只想在用户从 QTableView 拖动项目并释放左键时捕获 mouseRelease 事件。

我想在我的应用中突出显示可能的拖放区,例如更改小部件的背景。 我首先通过重新实现来检测拖动开始:

void LibraryTableView::startDrag( Qt::DropActions supportedActions )

    m_dragReleased = false;
    emit dragStart();
    QTableView::startDrag(supportedActions);

并发出我自己的信号。

现在 dropzone 已经改变了,我需要像以前一样捕捉释放事件来重新绘制 dropzone 无论拖放是否成功!

我尝试了不同的模型,重新实现了 4 个鼠标事件和 eventFilter,但鼠标释放事件从未被捕获。

这是我的代码:

void LibraryTableView::mouseDoubleClickEvent( QMouseEvent* event )

    QTableView::mouseDoubleClickEvent(event);


void LibraryTableView::mouseMoveEvent( QMouseEvent* event )

    qDebug() << "move";
    QTableView::mouseMoveEvent(event);


void LibraryTableView::mousePressEvent( QMouseEvent* event )

    qDebug() << "press";
    QTableView::mousePressEvent(event);


void LibraryTableView::mouseReleaseEvent( QMouseEvent* event )

    qDebug() << "real"; // Never called when drag ends ...
    QTableView::mouseReleaseEvent(event);

所以,这是一个错误? 如果你知道一个技巧,那对我有很大帮助。

谢谢!

编辑:我无法为我的应用程序中的每个小部件重新实现 dropEvent,如果用户在另一个应用程序中拖放元素,我仍然想捕获释放事件...

【问题讨论】:

Drop 事件发生在表格视图之外? 然后鼠标释放在那个小部件上被“捕获”。 【参考方案1】:

如上所述,已经 3 年了,但感谢上一个答案,我找到了一个更简单的解决方案来解决这个问题。

void LibraryTableView::startDrag( Qt::DropActions supportedActions )

    m_dragReleased = false;
    emit dragStart();
    QTableView::startDrag(supportedActions);

    //CODE HERE WILL BE EXECUTED ONLY WHEN THE MOUSE BUTTON HAS
    //BEEN RELEASED SO YOU CAN DO THE FOLLOWING
    emit dragStop();

【讨论】:

【参考方案2】:

自从提出这个问题三年后,这个 Qt 问题在 Qt 5.4 中仍然存在。最近我遇到了同样的问题:掉到应用程序之外并且没有 MouseReleaseEvent。解决方案很简单,并不是真正的技巧:

启动拖放的 mousePressEvent 如下所示(简化):

void DragNDropListView::mousePressEvent(QMouseEvent *event)
        ....
        QDrag *drag = new QDrag(this);
        QMimeData *mimeData = new QMimeData;
        mimeData->setData("application/x-xxxxxx", QByteArray());
        drag->setMimeData(mimeData);
        drag->exec();
            // The d&d ended here. Inside the widget where the drag
            // started, a mouseReleaseEvent would have been fired.
            // Outside this widget not.
            // drag->mimeData() is here still available.
        
    

技巧很简单:drag->exec() 启动它自己的事件循环,释放鼠标按钮时退出。 drag->exec();之后的鼠标位置可以用QCursor来确定。

【讨论】:

【参考方案3】:

对于QTableView,您必须重新实现三个函数以支持 dnd:

void dragEnterEvent ( QDragEnterEvent * event ) - 在这个函数中鼠标进入小部件 void QAbstractItemView::dragMoveEvent ( QDragMoveEvent * event ) - 在此功能中,您可以更新拖放区突出显示 void QAbstractItemView::dropEvent ( QDropEvent * event ) - 在这个函数中你决定是否接受这个事件

【讨论】:

drop发生在不同的widget中,QTableView是dragOnly 在这种情况下,dropEvent 应该在发生丢弃的小部件中重新实现。 如果用户从我的应用程序中删除了一个元素,我仍然想抓住鼠标Release ...无论小部件是否接受drop。【参考方案4】:

我遇到了类似的问题,我很不高兴发现 MouseReleaseEvent 在拖动结束时没有被触发。

我刚刚使用了 DragLeaveEvent 并关闭了我的变量,就像我在 MouseReleaseEvent 中所做的那样。如果用户拖出应用程序,然后重新打开,那些先前关闭的变量将在 DragMoveEvent 中重新启用(假设它被接受)。

至少这是我的伎俩。希望对您有所帮助。

【讨论】:

以上是关于拖动结束时未调用 QTableView mouseRelease 事件,错误?的主要内容,如果未能解决你的问题,请参考以下文章

QTableView 固定列宽度(鼠标拖动后,仍可固定)

拖动地图时未获取当前位置

C# 在面板周围拖动控件

输入类型 = 范围上的 onchange 事件在拖动时未在 Firefox 中触发

QTableView:如何在开始/结束编辑时做些啥?

动画中断时未调用 UIView 动画完成块