PyQt4拖放在dragEnter之前接收到mouseReleaseEvent
PyQt4 drag and drop receives mouseReleaseEvent before dragEnter
我正在尝试在 QTableWidget 中拖放行。
拖放操作本身运行良好,但是当我在一行上快速单击并释放鼠标按钮时,拖放事件永远不会被调用。即使松开鼠标,光标仍处于拖动模式,直到我再次单击。
当我在一行上慢慢点击一个释放,到select它时,事件是:
- 鼠标按下事件
- 拖动输入事件
- dropEvent
当我快速点击和释放时,事件是:
- 鼠标按下事件
- 鼠标释放事件
- 拖动输入事件
并且仅当我再次单击时才会调用 dropEvent。
这可能是因为 dragEnterEvent(我认为永远不应该调用)'hides' 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()
非常感谢
感谢 musicamante 为我指明了正确的方向。
这是 QTableWidget 的工作实现,支持拖放 table 行:
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()
我正在尝试在 QTableWidget 中拖放行。
拖放操作本身运行良好,但是当我在一行上快速单击并释放鼠标按钮时,拖放事件永远不会被调用。即使松开鼠标,光标仍处于拖动模式,直到我再次单击。
当我在一行上慢慢点击一个释放,到select它时,事件是: - 鼠标按下事件 - 拖动输入事件 - dropEvent
当我快速点击和释放时,事件是: - 鼠标按下事件 - 鼠标释放事件 - 拖动输入事件 并且仅当我再次单击时才会调用 dropEvent。
这可能是因为 dragEnterEvent(我认为永远不应该调用)'hides' 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()
非常感谢
感谢 musicamante 为我指明了正确的方向。 这是 QTableWidget 的工作实现,支持拖放 table 行:
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()