4

I'm trying to write a program that will interact with QGraphicsView. I want to gather mouse and keyboard events when the happen in the QGraphicsView. For example, if the user clicks on the QGraphicsView widget I will get the mouse position, something like that. I can hard code it rather easily, but I want to use QtDesigner because the UI will be changing frequently.

This is the code that I have for the gui.py. A simple widget with a QGraphicsView in it.

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_graphicsViewWidget(object):
    def setupUi(self, graphicsViewWidget):
        graphicsViewWidget.setObjectName(_fromUtf8("graphicsViewWidget"))
        graphicsViewWidget.resize(400, 300)
        graphicsViewWidget.setMouseTracking(True)
        self.graphicsView = QtGui.QGraphicsView(graphicsViewWidget)
        self.graphicsView.setGeometry(QtCore.QRect(70, 40, 256, 192))
        self.graphicsView.setObjectName(_fromUtf8("graphicsView"))

        self.retranslateUi(graphicsViewWidget)
        QtCore.QMetaObject.connectSlotsByName(graphicsViewWidget)

    def retranslateUi(self, graphicsViewWidget):
        graphicsViewWidget.setWindowTitle(QtGui.QApplication.translate("graphicsViewWidget", "Form", None, QtGui.QApplication.UnicodeUTF8))

The code for the program:

#!/usr/bin/python -d

import sys
from PyQt4 import QtCore, QtGui
from gui import Ui_graphicsViewWidget

class MyForm(QtGui.QMainWindow):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_graphicsViewWidget()
        self.ui.setupUi(self)
        QtCore.QObject.connect(self.ui.graphicsView, QtCore.SIGNAL("moved"), self.test)

    def mouseMoveEvent(self, event):
        print "Mouse Pointer is currently hovering at: ", event.pos()
        self.emit(QtCore.SIGNAL("moved"), event)

    def test(self, event):
        print('in test')

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = MyForm()
    myapp.show()
    sys.exit(app.exec_())

When I run this code, it gives me the opposite of what I want. I get the mouse position everywhere except for inside the QGraphicsView.

I'm sure it's a problem with my QObject.connect. But every time I go back and read about signals and slots it makes sense but I can't get it.

Please help, I've been banging my head for the past few days now. I'm sorry if this as been asked before but I've been through all the threads on this topic and I can't get anywhere.

Thanks

Jeff
  • 6,932
  • 7
  • 42
  • 72
  • In your gui.py file, the line `self.graphicsView = MyForm(graphicsViewWidget)` throws an exception because `MyForm` is not defined. I'm not sure exactly what you meant to do there. Can you fix that line? – Stephen Terry Sep 23 '11 at 12:15
  • Sorry, MyForm should be QtGui.QGraphicsView. I fixed it in the thread and ran it on my computer should be working now. – Jeff Sep 23 '11 at 16:37
  • Just as a suggestion, if you import using `from PyQt4.QtGui import *` and `from PyQt4.QtCore import *`, you can remove all instances of `QtCore.` and `QtGui.`, making the code more readable. – Blender Sep 23 '11 at 16:44

1 Answers1

3

The signal must come from the QGraphicsView object that was defined in the ui.

You can create a class derived from QGraphicsView like this

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyView(QGraphicsView):
    moved = pyqtSignal(QMouseEvent)

    def __init__(self, parent = None):
        super(MyView, self).__init__(parent)

    def mouseMoveEvent(self, event):
        # call the base method to be sure the events are forwarded to the scene
        super(MyView, self).mouseMoveEvent(event)

        print "Mouse Pointer is currently hovering at: ", event.pos()
        self.moved.emit(event)

Then, in the designer:

  • right-click on the QGraphicsView then Promote to
  • write the class name in the Promoted Class Name field (e.g. "MyView"),
  • write the file name where that class is in the Header file field but without the .py extension,
  • click on the Add button and then on the Promote button.

And you can regenerate your file gui.py with pyuic4.

alexisdm
  • 29,448
  • 6
  • 64
  • 99
  • Very nice explanation, thanks :) I just have one little question, is it somehow possible to make QtDesigner know which slots/signals you've created in the file (or the other way around). It seems pointless to have to define them 2 times. – Wolph Jul 20 '12 at 09:00
  • @WoLpH I guess you could create a plugin ([like that](http://diotavelli.net/PyQtWiki/Using_Python_Custom_Widgets_in_Qt_Designer), but it seems complicated if you only use the class in one project. – alexisdm Jul 20 '12 at 23:10
  • Thanks for the advice, plugins might be more trouble than they're worth in this case. But it's farily easy to integrate these days so I'll just mix them :) – Wolph Jul 21 '12 at 00:57