Custom cursor in QGIS plugin

Last january I developed QGIS plugin called Transectizer. Fortunately it was catalogued and sent to the box (or, who knows if a coffin) of the expermiental plugins.

Custom cursor showing bearing

A custom, chatty QGIS plugin cursor showing the bearing of the rubberband being drawn.

Yes, I said fortunately, because that prompted me towards changing some features of the plugin. One of these features is the ability of the plugin of give some feedback to the user about the bearing of a line drawn in the canvas, to make possible to interactively choose a certain parameter that is needed for the plugin to work.

In the first version of the plugin (the second is upcoming, see below), it just updates the text of a LineEdit widget inside the QGIS plugin dialog. This is a relatively simple task, if you have already dived into the somehow spread information available on the internet about QGIS plugin development. The first place to start is, of course the QGIS plugin repository where there is a growing documentation about plugin programming in QGIS, but Anita Graser’s Blog, for instance, are places where you can find very useful documentation and, ever better, examples. Also you can dig in other plugins to see how others have solved the same ,or similar, problems that you are facing.

But in the next version, which will be released in two weeks or less if Mr. Pareto lets me do it, I want to get that information in the mouse cursor, so the plugin use is more comfortable and easy to use. And to get that kind of behavior, you must change your mouse’s cursor shape.

First step: change the shape of your QGIS plugin mouse cursor

WARNING: This article has been written by an amateur, self-taught  programme (not even a complete programmer, you know)… please don’t blame on me too much if the programming-related terminology is not accurate. Thanks.

First of all, it is useful only if your QGIS plugin needs to interact with the map canvas. In that case, your plugin must have a QgsMapTool map tool enabled to perform canvas interactions. This is very well explained in the pyQGIS cookbook, and, to simplify, what you have to do is to subclass QgsMapTool or one of its derived classes, depending on what you want to achieve (a zoom tool, an identifier tool or a point emmiting tool, among others) and implement the cursor changing code inside the new class. Usually you’ll want to do change the cursor in response to a canvas interaction, so the natural way of achieving this is to override the mouse-event related methods of the these classes (canvasMoveEvent, canvasClickEvent, etc.):

Now you have to change the cursor. To make this first, take a look of the Pyqt4 documentation about QCursor. Now, bear in mind that the cursor itself belongs, say so, to the mapCanvas which you passed to your mapTool in its creation. So you have just to get a reference to it and change the cursor through the mapCanvas method setCursor, replacing the cursor for the one you want. In the following example, we are going to set a custom pixmap for the cursor when the user clicks in the canvas and set it back to a standard cursor when the button is released.

 And now… chatty cursors in QGIS plugin

Well, changing the cursor is pretty easy and so is to make our cursor talkative or, better informative. In the case of the Transectizer QGIS plugin, what I wanted was to show the bearing of the line currently being edited in the cursor or maybe you want to show a distance, the cursor coordinates or whatever but, in any case, in real time.

So… what have we to do? Well, that’s pretty simple. We have to implement the method canvasMoveEvent in our mapTool making it change the cursor every time it is called. And what we do is to paint over our cursor’s pixmap the information we want to show.

To perform this, we have to create a QPainter on our pixmap and then act as we did in the canvasPressEvent: first, create the QCursor and then assigning our cursor to our canvas:

Well, and that’s all… you could use it to improve a lot your plugins  with canvas interaction, giving simple but eye-candy feedback to your users.

I have to check if big cursors can be used in QGIS, for instance to show the whole set of coordinates of a point. Or, to make it inmediate, to improve the ValueTool plugin to show the value in the cursor itself, rather than in a widget.

I hope that it would be useful to you in your plugins!!!