QgsMapCanvasItem and mouse events -- Python

6 messages Options
Embed this post
Permalink
Florian El Ahdab

QgsMapCanvasItem and mouse events -- Python

Reply Threaded More More options
Print post
Permalink
Hi.

It seems my previous mail didn't make it to the list with the text... weird.

Let me try again.

I am trying to subclass QgsMapCanvasItem so as do display items on top
of the maps.

I would like those items to react to mouse events.

I have implemented the handles for the mouse events as the Qt API
suggests, but my items do not seem to receive any events. The
isUnderMouse method returns coherent results when run from the python
console.

The source file for my geographicitems is included.

Thanks for your help.

import random
import threading
import time
import socket
from qgis import *
from qgis.core import *
from qgis.gui import *
import PyQt4.QtGui as QtGui
import PyQt4.QtCore as QtCore
               
class GeographicItem(QgsMapCanvasItem):
               
        def __init__(self,iface):
                self.iface=iface
                self.canvas = iface.mapCanvas()
                QgsMapCanvasItem.__init__(self,self.canvas)
                self.position=QgsPoint()
                self.identification=0
                self.tn=0
                self.override = False
                self.overrideColor=QtGui.QColor(0,255,255)
               
                self.setHandlesChildEvents(True)
                self.GraphicsItemFlags=QtGui.QGraphicsItem.ItemIsSelectable | QtGui.QGraphicsItem.ItemIsFocusable
               
                self.texte = QtGui.QGraphicsTextItem(QtCore.QString("Name"),self,self.canvas.scene())
                self.texte.setPos(-10,10)
                self.rec=QtGui.QGraphicsRectItem(0,0,10,10,self,self.canvas.scene())
                QtCore.QObject.connect(self.canvas,QtCore.SIGNAL( "renderComplete( QPainter * )" ),self.renderComplete)
       
        def acceptedMouseEvents(self):
                result=QtCore.Qt.LeftButton | QtCore.Qt.RightButton | QtCore.Qt.MidButton
                return result
       
        #def acceptsHoverEvents(self):
        # return True
       
        def mousePressEvent(self, event):
                self.setTN(123)
       
        def mouseReleaseEvent(self, event):
                self.setTN(123)
               
        #def keyPressEvent(self,event):
        # self.setTN(123)

        #def hoverEnterEvent(self,event):
        # self.override= True
        # self.updateStyles()
               
        #def hoverExitEvent(self,event):
        # self.override= False
        # self.updateStyles()

        def boundingRect(self):
                return QtCore.QRectF(0 , 0 , 10 , 10 );
       
        def getTN(self):
                return self.tn
               
        def setTN(self,tn):
                self.tn=tn
                self.canvas.scene().removeItem(self.texte)
                del(self.texte)
                self.texte = QtGui.QGraphicsTextItem(QtCore.QString(oct(self.tn)),self,self.canvas.scene())
                self.updateStyles()
       
        def setIdentification(self, identification):
                self.identification=identification
                self.updateStyles()
       
        def setPositionGeo(self,position):
                self.position=position
                self.updateStyles()
                self.setPos(self.toCanvasCoordinates(self.position))
                self.update()
       
        def updateStyles(self):
                pen=self.rec.pen()
                if not self.override:
                        if self.identification < 5:
                                color=QtGui.QColor(255,0,0)
                        else:
                                color=QtGui.QColor(0,0,255)
                else:
                        color=self.overrideColor
                pen.setColor(color)
                self.texte.setDefaultTextColor(color)
                self.rec.setPen(pen)
                self.texte.update()
                self.update()
       
        def paint(self,painter,option,widget):
                return
               
        def renderComplete(self,painter):
                self.updateStyles()
                self.setPos(self.toCanvasCoordinates(self.position))
                self.update()
               
        def removeFromCanvas(self):
                self.canvas.scene().removeItem(self)

        def addToCanvas(self):
                self.canvas.scene().addItem(self)
_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer
Florian El Ahdab

Re: QgsMapCanvasItem and mouse events -- Python

Reply Threaded More More options
Print post
Permalink
Hi Tim.

Thanks for your answer.

The renderComplete signal works perfectly with the code I sent, and my
items get refreshed correctly after the canvas is rendered. The SLOT
macro is not needed for the destination of the signal (but I don't
really know the details of PyQT...)

My problem is about the mouse events. According to the QGraphicsItem
API documentation, if I override the mousePressEvent and
mouseReleaseEvent methods, my objects should get the corresponding
events without further settings... but they don't.

Thanks for the help.
Florian

On 11/1/09, Mailing Lists <[hidden email]> wrote:

> Hi
>
> On Sun, Nov 1, 2009 at 12:00 PM, Florian El Ahdab <[hidden email]>
> wrote:
>> Hi.
>>
>> It seems my previous mail didn't make it to the list with the text...
>> weird.
>>
>> Let me try again.
>>
>> I am trying to subclass QgsMapCanvasItem so as do display items on top
>> of the maps.
>>
>> I would like those items to react to mouse events.
>>
>> I have implemented the handles for the mouse events as the Qt API
>> suggests, but my items do not seem to receive any events. The
>> isUnderMouse method returns coherent results when run from the python
>> console.
>>
>
> QtCore.QObject.connect(self.canvas,QtCore.SIGNAL( "renderComplete(
> QPainter * )" ),self.renderComplete)
>
>
> Dont you have to specify SLOT part of the signal macro?
>
> Regards
>
> Tim
>
>
>> The source file for my geographicitems is included.
>>
>> Thanks for your help.
>>
>> _______________________________________________
>> Qgis-developer mailing list
>> [hidden email]
>> http://lists.osgeo.org/mailman/listinfo/qgis-developer
>>
>>
>
>
>
> --
> Tim Sutton - QGIS Project Steering Committee Member (Release  Manager)
> ==============================================
> Please do not email me off-list with technical
> support questions. Using the lists will gain
> more exposure for your issues and the knowledge
> surrounding your issue will be shared with all.
>
> Visit http://linfiniti.com to find out about:
>  * QGIS programming and support services
>  * Mapserver and PostGIS based hosting plans
>  * FOSS Consulting Services
> Skype: timlinux
> Irc: timlinux on #qgis at freenode.net
> ==============================================
>
_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer
Martin Dobias

Re: QgsMapCanvasItem and mouse events -- Python

Reply Threaded More More options
Print post
Permalink
On Sun, Nov 1, 2009 at 10:54 PM, Florian El Ahdab <[hidden email]> wrote:

> Hi Tim.
>
> Thanks for your answer.
>
> The renderComplete signal works perfectly with the code I sent, and my
> items get refreshed correctly after the canvas is rendered. The SLOT
> macro is not needed for the destination of the signal (but I don't
> really know the details of PyQT...)
>
> My problem is about the mouse events. According to the QGraphicsItem
> API documentation, if I override the mousePressEvent and
> mouseReleaseEvent methods, my objects should get the corresponding
> events without further settings... but they don't.

Hi Florian,

you should use canvasPressEvent, canvasReleaseEvent and
canvasMoveEvent functions to track mouse cursor on map canvas.

Martin
_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer
Florian El Ahdab

Re: QgsMapCanvasItem and mouse events -- Python

Reply Threaded More More options
Print post
Permalink
Hi

That's a good idea. 
I will implement the canvas events for now...

...but I would really like to understand why those events are not delivered to my objects. I think they should, and although it is not a big problem, I wouldn't have to rewrite the tests needed to handle the canvasEvent... The QGraphicsView should take care of this for me and send the event automatically to the right objects.

Thanks.
Florian

On Mon, Nov 2, 2009 at 10:40 AM, Martin Dobias <wonder.sk@gmail.com> wrote:
On Sun, Nov 1, 2009 at 10:54 PM, Florian El Ahdab <[hidden email]> wrote:
> Hi Tim.
>
> Thanks for your answer.
>
> The renderComplete signal works perfectly with the code I sent, and my
> items get refreshed correctly after the canvas is rendered. The SLOT
> macro is not needed for the destination of the signal (but I don't
> really know the details of PyQT...)
>
> My problem is about the mouse events. According to the QGraphicsItem
> API documentation, if I override the mousePressEvent and
> mouseReleaseEvent methods, my objects should get the corresponding
> events without further settings... but they don't.

Hi Florian,

you should use canvasPressEvent, canvasReleaseEvent and
canvasMoveEvent functions to track mouse cursor on map canvas.

Martin


_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer
Martin Dobias

Re: QgsMapCanvasItem and mouse events -- Python

Reply Threaded More More options
Print post
Permalink
On Mon, Nov 2, 2009 at 2:22 PM, Florian El Ahdab <[hidden email]> wrote:
> Hi
> That's a good idea.
> I will implement the canvas events for now...
> ...but I would really like to understand why those events are not delivered
> to my objects. I think they should, and although it is not a big problem, I
> wouldn't have to rewrite the tests needed to handle the canvasEvent... The
> QGraphicsView should take care of this for me and send the event
> automatically to the right objects.

I think the default implementation of mouse*Event() functions in
QGraphicsView automatically propagates these events to the items. In
QGIS we use our own implementation of these functions so the events
are propagated to current map tool instead of canvas items.

Regards
Martin
_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer
Martin Dobias

Re: QgsMapCanvasItem and mouse events -- Python

Reply Threaded More More options
Print post
Permalink
On Tue, Nov 3, 2009 at 2:03 PM, Florian El Ahdab <[hidden email]> wrote:

> Hi.
> Thanks for coming back to me about this issue.
> Yes, I went through the sources of Qgis to discover the reason of my
> problem.
> The mouse events are propagated to the active map tool unless some boutons
> are pressed which trigger a pan, except for the MouseMoveEvent which is
> converted into the xyCoordinates signal available for everyone.
> The key events are converted into Qt signals (KeyPressed and KeyReleased)
> and propagated.
> If I understand currectly, there is no way for a user to override this
> behaviour so as to catch all events related to the canvas (Except subclass
> the QgsMapCanvas to get all the events... which is only possible in a custom
> app I presume, not in QGis with a plugin).

That's right. If you need to interact with map canvas items, you can
simply create a map tool which will implement the functionality you
need.

Martin
_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer