我正在尝试在QTableWidget内拖放行。
拖放操作本身运行良好,但是当我单击并连续释放鼠标按钮rapidly时,永远不会调用drop事件。即使释放了鼠标,光标仍处于拖动模式,直到再次单击。
当我连续缓慢单击发行版以选择它时,事件是:-mousePressEvent-dragEnterEvent-dropEvent
当我单击并快速释放时,事件为:-mousePressEvent-mouseReleaseEvent-dragEnterEvent仅在再次单击时才会调用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()
非常感谢
我最终得出结论,从我的观点出发,最简单的解决方案是通过确保没有释放鼠标来保护drag.start。我确信有更好的解决方案,但是我找不到它,经过大量搜索和误导之后,这是我的工作类(在QT <4.3和Linux上):
from PyQt4.QtGui import QTableWidget, QAbstractItemView, QDrag
from PyQt4.QtCore import QMimeData, Qt, pyqtSignal
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):
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)
if not self.released:
# this will prevent the case where the click release is very quick and we release before the drag/drop start
drag.start(Qt.MoveAction)
def dragEnterEvent(self, e):
e.accept()
def dragMoveEvent(self, e):
e.accept()
def mouseReleaseEvent(self, e):
self.released = True
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():
self.moveRow.emit(start_index, index.row())
event.accept()