shybovycha
shybovycha

Reputation: 12275

PyQt event emmitted twice

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

Answers (1)

shybovycha
shybovycha

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

Related Questions