0

1. Problem explained

I want to make the mouse shape change from the I-beam into a pointing hand when hovering over clickable text in a QTextEdit() widget. Thanks to the following StackOverflow question, I know how to achieve this goal:

Clickable hyperlink in QTextEdit

Unfortunately, the way to change the cursor shape relies on this global function:

QApplication.setOverrideCursor(Qt.PointingHandCursor)

This works, but has unintended consequences when you move the mouse over other widgets. A cleaner way to change the mouse shape would be to use this function:

self.setCursor(Qt.PointingHandCursor)

with self being the QWidget() of interest. Unfortunately, this has no effect on a QTextEdit() widget.

2. Minimalistic example

Consider the following minimalistic self-contained sample code:

import sys
from PyQt5.Qt import QDesktopServices, QUrl, QApplication, QColor, Qt
from PyQt5.QtWidgets import QTextEdit

class MyWidget(QTextEdit):
    def __init__(self):
        super().__init__()
        self.setMouseTracking(True)
        return

    def mousePressEvent(self, e):
        super().mousePressEvent(e)
        self.anchor = self.anchorAt(e.pos())
        if self.anchor:
            self.setCursor(Qt.PointingHandCursor)
            # QApplication.setOverrideCursor(Qt.PointingHandCursor)
        return

    def mouseReleaseEvent(self, e):
        super().mouseReleaseEvent(e)
        if self.anchor:
            QDesktopServices.openUrl(QUrl(self.anchor))
            self.setCursor(Qt.ArrowCursor)
            # QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.anchor = None
        return

    def mouseMoveEvent(self, e) -> None:
        super().mouseMoveEvent(e)
        self.anchor = self.anchorAt(e.pos())
        if self.anchor:
            self.setCursor(Qt.PointingHandCursor)
            # QApplication.setOverrideCursor(Qt.PointingHandCursor)
        else:
            self.setCursor(Qt.ArrowCursor)
            # QApplication.setOverrideCursor(Qt.ArrowCursor)
        return

if __name__== '__main__':
    app = QApplication(sys.argv)
    editor = MyWidget()
    cursor = editor.textCursor()
    fmt = cursor.charFormat()
    fmt.setForeground(QColor('blue'))
    address = 'http://example.com'
    fmt.setAnchor(True)
    fmt.setAnchorHref(address)
    fmt.setToolTip(address)
    cursor.insertText("This is a link", fmt)
    editor.show()
    app.exec_()

Please tinker around a bit with this sample code. You will notice:

  • Activate the lines QApplication.setOverrideCursor(Qt.PointingHandCursor) and it works.

  • Use the cleaner self.setCursor(Qt.PointingHandCursor) (let setOverrideCursor() be commented out) and nothing happens.

3. Solution?

Do you know a way to get self.setCursor(Qt.PointingHandCursor) working properly on a QTextEdit() widget? Or do you know another approach to achieve the same goal - without using the setOverrideCursor() function?

K.Mulier
  • 8,069
  • 15
  • 79
  • 141

1 Answers1

0

The key is to use:

self.viewport().setCursor(Qt.PointingHandCursor)

instead of:

self.setCursor(Qt.PointingHandCursor)

I got the inspiration from:

How to set cursor shape to '>' in a QTextEdit?

K.Mulier
  • 8,069
  • 15
  • 79
  • 141