8

1. Intro

I'm creating an application in Python 3.7 with PyQt5 for the GUI. I would like to customize the mouse cursors in the application.

Let's start from the standard cursor set in Qt5 as shown in a table here: https://doc.qt.io/qt-5/qt.html#CursorShape-enum. You will notice that Qt5 has a dedicated Enum Qt::CursorShape describing the role of the corresponding cursor. For example:

Qt standard cursors

 
I would like to replace each Standard Qt cursor with a custom made one:

Custom cursors

 

2. First approach

At first I tried something like this:

pixmap = QPixmap("C:/../my_arrow.png")
cursor = QCursor(pixmap, 32, 32)
QApplication.setOverrideCursor(cursor)

Unfortunately, this approach is not good for my purpose. From the documentation:

Application override cursors are intended for showing the user that the application is in a special state, for example during an operation that might take some time.
 
The override cursor will be displayed in all the application's widgets until restoreOverrideCursor() or another setOverrideCursor() is called.

In other words, using the setOverrideCursor() approach has two downsides:

  1. I would have to track manually to which role the mouse pointer should change, call setOverrideCursor() each time and feed it with the proper QCursor().

  2. I'd need to track wherever Qt automatically calls restoreOverrideCursor(), because that effectively undoes my own changes. It would be a constant battle against Qt.

 

3. Second approach

My second approach was playing around with the setCursor() function:

pixmap = QPixmap("C:/../Arrow.png")
cursor = QCursor(pixmap, 32, 32)
my_widget.setCursor(cursor)

I do this on the toplevel widget - the QMainWindow() - such that the effect is applied on the whole application.

It works great, but it has one downside. This function only changes the "default cursor" (the pointing arrow) but that's it. All the special cursors are still the same.

 
In fact, I would like to do something like this:

# Note: 'mainwin' is the QMainWindow().
mainwin.setCursor( QCursor(QPixmap("C:/../Arrow.png"),     32, 32), Qt.ArrowCursor     )
mainwin.setCursor( QCursor(QPixmap("C:/../UpArrow.png"),   32, 32), Qt.UpArrowCursor   )
mainwin.setCursor( QCursor(QPixmap("C:/../Cross.png"),     32, 32), Qt.CrossCursor     )
mainwin.setCursor( QCursor(QPixmap("C:/../Wait.png"),      32, 32), Qt.WaitCursor      )
mainwin.setCursor( QCursor(QPixmap("C:/../IBeam.png"),     32, 32), Qt.IBeamCursor     )
mainwin.setCursor( QCursor(QPixmap("C:/../SizeVer.png"),   32, 32), Qt.SizeVerCursor   )
mainwin.setCursor( QCursor(QPixmap("C:/../SizeHor.png"),   32, 32), Qt.SizeHorCursor   )
mainwin.setCursor( QCursor(QPixmap("C:/../SizeBDiag.png"), 32, 32), Qt.SizeBDiagCursor )
mainwin.setCursor( QCursor(QPixmap("C:/../SizeFDiag.png"), 32, 32), Qt.SizeFDiagCursor )
...

Unfortunately, that's not how the setCursor() function works.

 
Do you have a solution that matches best my purpose?

 

4. Resources

I've learned a lot from the following sources:

Unfortunately, none of them provided the solution to my problem. I just mention them here, because they are related to - but not the same as(!) - what I'm trying to do.

K.Mulier
  • 8,069
  • 15
  • 79
  • 141
  • IMHO it is impossible to change the cursors since its implementation is in the private api of Qt – eyllanesc May 15 '19 at 17:56
  • Hi @eyllanesc, Thank you for looking at the problem. Let us hope there is a way to do it. I honestly don't know how - but that's what StackOverflow is for :-) – K.Mulier May 16 '19 at 14:33
  • [This](https://forum.qt.io/topic/86829/how-to-create-a-cursor-theme-for-an-entire-qt-application/8) also talks about the excat thing you want to do. Their result is also that it is not possible. I think the general problem is that the OS draws the cursor (am i right with this?) and you are not able to get notified or something when the when the cursor changes. – Tim Körner Dec 19 '19 at 07:54

1 Answers1

2
# I'm coming```.

# 1. Set the cursor map
self.cursor_pix = QPixmap('exa.png')

# 2. Scale textures
self.cursor_scaled_pix = self.cursor_pix.scaled(QSize(20, 20), Qt.KeepAspectRatio)

# 3. Set cursor style and cursor focus position
self.current_cursor = QCursor(self.cursor_scaled_pix, -1, -1)

# 4. Set the cursor for the specified window
widget.setCursor(self.current_cursor)
parzulpan
  • 21
  • 2