Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cross-platform custom cursors for Qt, cursor in resource file

I feel like I'm missing something since I can't see any way to easily do a cross-platform cursor in Qt. That is, I'd like to use a standard cursor editor, or just a common cursor file type, and stick it in the resource file.

I see a couple platform specific manners providing handles (meaning I couldn't load from a resource) or a generic way taking a pixmap. In the pixmap method I would then have to find someway to store the hotspot along with the pixmap.

I don't want animated cursors, just a plain color image (32x32).

What is the easiest way to handling this?

like image 761
edA-qa mort-ora-y Avatar asked Feb 24 '23 16:02

edA-qa mort-ora-y


1 Answers

I'm currently working on an application where I'd like to have some nice custom cursors. The way I'm doing that is:

  • Add an image to a Qt resource file (*.qrc) - I am working with PNG with transparency exported from an SVG (always have your original art sources in SVG for things like this in case you need scaling)

     <RCC>
       <qresource prefix="/">
         <file alias="default">cursors/cursor_default.png</file>
       </qresource>
     </RCC>
    

This will allow you to ship your cursors along with your application since Qt resource files are converted to C++ sources, which are then added to your binary

  • In your source code do:

     QPixmap cursor_pixmap = QPixmap(":cursor_default");
     QCursor cursor_default = QCursor(cursor_pixmap, 0, 0);
     setCursor(cursor_default);
    

There are two important things to notice here both related to the constructor of the QCursor - the pixmap you add to it and the hotspot coordinates (here both set to 0 which is the top left corner of the pixmap that represents the shape of your cursor). There are actually 2 constructors for QCursor which are imho useful here:

- `QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX = -1, int hotY = -1)` - this allows you to use a mask to manipulate the pixels of your cursor 
- `QCursor::QCursor(const QPixmap &pixmap, int hotX = -1, int hotY = -1)` - if you are working with a PNG or other supported image format which allows transparency you can omit the mask as it is in my case.

The hotspot is a very essential part of a cursor - it tells your application which part of your cursor is the "trigger" that is the spot which does something compared to the rest which is just fancy visuals and nothing functional.

enter image description here

While looking for resources on Qt customization of cursors I found this article (the image above is from it), which I can totally recommend every one, interested in this topic, to read.

In terms of storing the hotspot I don't think that something like this is necessary. After all your resource files are compiled and added to the binary hence when you assign a hotspot to a cursor inside your code it will be there. I doubt that any OS actually has a format (let alone multi-platform one) that stores both the cursor and its hotspot due to the fact that depending on the application you may want to change the hotspot (for example due to scaling the bitmap itself in order to have multiple sizes) which would be a lot more difficult if you have it bound to the cursor's bitmap. If you really want to go the distance with this (I would advise against it) you can create your own custom file format which contains both. Since the Qt resource files are - to my knowledge - meant for managing images you would have to implement the whole IO mechanics in order to support your custom format.

Hope this helps. The solution above is as cross-platform as you can get with the Qt framework. Note however that the custom QCursor will only be available inside your application and wherever you have set it in. Cursor that is above the window frame for example is considered OS-specific due to the fact that the window frame itself is an OS-specific feature and if you want to alter its behaviour you will have to go a lot deeper (and also outside Qt's safe zone) meaning check how cursors are handled on an OS-level.

like image 79
rbaleksandar Avatar answered Apr 29 '23 14:04

rbaleksandar