【问题标题】:PyQt4 drag and drop receives mouseReleaseEvent before dragEnterPyQt4拖放在dragEnter之前接收mouseReleaseEvent
【发布时间】:2020-04-03 15:27:13
【问题描述】:

我正在尝试在 QTableWidget 中拖放行。

拖放操作本身效果很好,但是当我在一行上快速单击并释放鼠标按钮时,永远不会调用 drop 事件。即使释放鼠标,光标仍处于拖动模式,直到我再次单击。

当我在一行上缓慢单击一个版本以选择它时,事件是: - 鼠标按下事件 - 拖动输入事件 - 丢弃事件

当我快速单击并释放时,事件是: - 鼠标按下事件 - 鼠标释放事件 - 拖动输入事件 只有当我再次点击时才会调用 dropEvent。

这可能是因为dragEnterEvent(我认为不应该被调用)将mouseReleaseEvent“隐藏”到拖动操作中。

有没有办法强制结束拖动操作?或者更好,防止拖动操作调用dragEnterEvent?

这是我的代码:

class DragDropTableWidget(QTableWidget):

    moveRow = pyqtSignal(int, int)

    def __init__(self, parent):
        super(QTableWidget, self).__init__(parent)

        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.viewport().setAcceptDrops(True)
        self.setDragDropOverwriteMode(False)
        self.setDropIndicatorShown(True)
        self.setSelectionMode(QAbstractItemView.SingleSelection)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setDragDropMode(QAbstractItemView.InternalMove)

        self.released = False

    def mousePressEvent(self, event):
        print('Mouse Press')
        self.released = False

        index = self.indexAt(event.pos())
        if not index.isValid():
            return

        row = index.row()
        self.selectRow(row)

        mime_data = QMimeData()
        mime_data.setData("index", str(row))

        drag = QDrag(self)
        drag.setMimeData(mime_data)
        drag.start(Qt.MoveAction)

    def dragEnterEvent(self, e):
        print('Drag Enter')
        if self.released:
            # todo: cancel drag and drop
            pass
        else:
            e.accept()

    def dragMoveEvent(self, e):
        e.accept()

    def mouseReleaseEvent(self, e):
        print('Mouse release')
        self.released = True

    def dropEvent(self, event):
        print('Drop event')
        if event.source() == self:
            index = self.indexAt(event.pos())
            if not index.isValid():
                event.accept()
                return
            start_index = int(event.mimeData().data("index"))
            if start_index != index.row():
                print ("dropEvent called from row {} on row {}".format(start_index, index.row()))
                self.moveRow.emit(start_index, index.row())

            event.accept()

非常感谢

【问题讨论】:

  • 我无法重现您的问题,因为即使“快速”单击,我也总是“正确”获得 drop 事件(不过,在 Linux 和 Wine 上使用 PyQt4 进行了测试,因此本机 Windows 实现可能会做出反应不同)。在任何情况下,不建议在鼠标单击时开始拖动操作(通常首选 mouseMoveEvent),并且立即获得 dragEnterEvent 是预期的行为。

标签: pyqt drag-and-drop qtablewidget


【解决方案1】:

感谢 musicamante 为我指明了正确的方向。 这是一个 QTableWidget 的工作实现,支持表格行的拖放:

class DragDropTableWidget(QTableWidget):
# signal sent on drag and drop end operation
moveRow = pyqtSignal(int, int)

def __init__(self, parent):
    super(QTableWidget, self).__init__(parent)

    self.setDragEnabled(True)
    self.setAcceptDrops(True)
    self.viewport().setAcceptDrops(True)
    self.setDragDropOverwriteMode(False)
    self.setDropIndicatorShown(True)
    self.setSelectionMode(QAbstractItemView.SingleSelection)
    self.setSelectionBehavior(QAbstractItemView.SelectRows)
    self.setDragDropMode(QAbstractItemView.InternalMove)

def mouseMoveEvent(self, event):
    if event.type() == QEvent.MouseMove and event.buttons() & Qt.LeftButton:
        index = self.indexAt(event.pos())
        if not index.isValid():
            return

        mime_data = QMimeData()
        mime_data.setData("index", str(index.row()))

        drag = QDrag(self)
        drag.setMimeData(mime_data)

        drag.start(Qt.MoveAction)

def dragEnterEvent(self, e):
    e.accept()

def dragMoveEvent(self, e):
    e.accept()

def dropEvent(self, event):
    if event.source() == self:
        index = self.indexAt(event.pos())
        if not index.isValid():
            event.accept()
            return
        start_index = int(event.mimeData().data("index"))
        if start_index != index.row():
            print ("dropEvent called from row {} on row {}".format(start_index, index.row()))
            self.moveRow.emit(start_index, index.row())

        event.accept()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 2012-01-14
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多