Reputation: 12275
I'm trying to implement drag-n-drop'in' items from QListWidget
to QGraphicsView
. I've inherited my own class MooView
from QGraphicsView
and encapsulated dragMove
, dragEnter
and drop
events. But while testing this out, i've noticed that each event is emmitted twice.
Here's my MooView
code:
from PyQt4 import QtCore, QtGui
class MooView(QtGui.QGraphicsView):
def __init__(self, parent = None):
QtGui.QGraphicsView.__init__(self, parent)
self.handlers = {}
self.handlers['dragEnter'] = []
self.handlers['dragEnter'].append(super(MooView, self).dragEnterEvent)
self.handlers['dragLeave'] = []
self.handlers['dragLeave'].append(super(MooView, self).dragLeaveEvent)
self.handlers['dragMove'] = []
self.handlers['dragMove'].append(super(MooView, self).dragMoveEvent)
self.handlers['drop'] = []
self.handlers['drop'].append(super(MooView, self).dropEvent)
def addDragEnterHandler(self, handler):
self.handlers['dragEnter'].append(handler)
def removeDragEnterHandler(self, handler):
self.handlers['dragEnter'].remove(handler)
def addDragLeaveHandler(self, handler):
self.handlers['dragLeave'].append(handler)
def removeDragLeaveHandler(self, handler):
self.handlers['dragLeave'].remove(handler)
def addDragMoveHandler(self, handler):
self.handlers['dragMove'].append(handler)
def removeDragMoveHandler(self, handler):
self.handlers['dragMove'].remove(handler)
def addDropHandler(self, handler):
self.handlers['drop'].append(handler)
def removeDropHandler(self, handler):
self.handlers['drop'].remove(handler)
# handlers
def dragEnterEvent(self, arg):
#res = super(MooView, self).dragEnterEvent(arg)
for h in self.handlers['dragEnter']:
h(arg)
#return res
def dragLeaveEvent(self, arg):
#res = super(MooView, self).dragLeaveEvent(arg)
for h in self.handlers['dragLeave']:
h(arg)
#return res
def dragMoveEvent(self, arg):
#res = super(MooView, self).dragMoveEvent(arg)
for h in self.handlers['dragMove']:
h(arg)
#return res
def dropEvent(self, arg):
#res = super(MooView, self).dropEvent(arg)
for h in self.handlers['drop']:
h(arg)
#return res
And this is how i run that core:
import sys
from PyQt4 import QtCore, QtGui, QtOpenGL
from window import Ui_MainWindow
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setWindowTitle('Hello, Qt!')
self.scene = QtGui.QGraphicsScene()
self.ui.workspace_view.setScene(self.scene)
rect = QtCore.QRectF(0, 0, 1000, 1000)
self.scene.setSceneRect(0, 0, rect.width(), rect.height())
self.ui.workspace_view.setViewport(QtOpenGL.QGLWidget())
icon = QtGui.QIcon(QtGui.QPixmap(":/Images/50.png"))
text = "50's element"
item = QtGui.QListWidgetItem(icon, text)
self.ui.element_list.addItem(item)
icon = QtGui.QIcon(QtGui.QPixmap(":/Images/40.png"))
text = "40's element"
item = QtGui.QListWidgetItem(icon, text)
self.ui.element_list.addItem(item)
self.ui.workspace_view.addDragEnterHandler(self.workspace_item_drag_enter)
self.ui.workspace_view.addDragMoveHandler(self.workspace_item_drag_move)
self.ui.workspace_view.addDropHandler(self.workspace_item_dropped)
def workspace_item_drag_move(self, e):
#print("item drag move")
e.accept()
def workspace_item_drag_enter(self, e):
print("item drag enter")
e.accept()
def workspace_item_dropped(self, e):
print("item dropped")
if (__name__ == "__main__"):
app = QtGui.QApplication(sys.argv)
myApp = Main()
myApp.show()
sys.exit(app.exec_())
When drag-n-dropping items, "item drag enter" and "item dropped" lines are printed twice each in the terminal, e.g.:
item drag enter
item drag enter
item dropped
item dropped
The question is: how it could be fixed???
Upvotes: 2
Views: 1233
Reputation: 12275
As i've read somewhere in the web, QGraphicsView
could pass events to its QGraphicsScene
in some cases. So it did here: when i inherited my class from QGraphicsScene
and used it as default for QGraphicsView
(replaced MooView
with QGraphicsView
; read the rest of this answer for details) it worked as i was expecting.
So, now i have two source parts: MooGraphicsScene.py
and main.py
. Here are they, respectively:
from PyQt4 import QtCore, QtGui
class MooGraphicsScene(QtGui.QGraphicsScene):
def __init__(self, parent = None):
QtGui.QGraphicsScene.__init__(self, parent)
def dragMoveEvent(selfs, e):
pass
def dropEvent(self, e):
print("Drop fired!")
def dragEnterEvent(self, e):
e.accept()
print("Drag entered!")
And this one:
import sys
from PyQt4 import QtCore, QtGui, QtOpenGL
from window import Ui_MainWindow
from MooGraphicsScene import MooGraphicsScene
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setWindowTitle('Hello, Qt!')
# Setup Workspace
self.scene = MooGraphicsScene()
self.ui.workspace_view.setScene(self.scene)
rect = QtCore.QRectF(0, 0, 1000, 1000)
self.scene.setSceneRect(0, 0, rect.width(), rect.height())
icon = QtGui.QIcon(QtGui.QPixmap(":/Images/50.png"))
text = "50's element"
item = QtGui.QListWidgetItem(icon, text)
self.ui.element_list.addItem(item)
icon = QtGui.QIcon(QtGui.QPixmap(":/Images/40.png"))
text = "40's element"
item = QtGui.QListWidgetItem(icon, text)
self.ui.element_list.addItem(item)
if (__name__ == "__main__"):
app = QtGui.QApplication(sys.argv)
myApp = Main()
myApp.show()
sys.exit(app.exec_())
Hope, this would help someone!
Upvotes: 2