I'm trying to draw a long cursor in Qt.
I already have a function to edit many lines of a QPlainTextEdit at the same time (<-> alt edition in Notepad++), and my current goal is to display the cursor.
---- old version -------
I wasn't the simplest way, but I planned on drawing the cursor in a QGraphicsScene on top of the QPlainTextEdit (could'nt think of another way). I had a QGraphicsView and Scene transparent on top of my QPlainTextEdit, the QPlainTextEdit is the one that catches the users's events. My current problem was that I didn't manage to scroll the QGraphicsScene.
I know it can work because of this old question : QGraphicsView inside QPlainTextEdit (scrollable widget) but they don't precise how they achieved that...
So at the moment I have my editor (a QPlainTextEdit)
class Editor(QPlainTextEdit):
def __init__(self):
super().__init__()
self.setLineWrapMode(QPlainTextEdit.NoWrap)
self.setCenterOnScroll(True)
# for the cursor
self.graphicScene = QGraphicsScene()
self.graphicScene.addText("Hello world")
self.view = AltGraphicsView(self.graphicScene, self)
self.view.show()
self.horizontalScrollBar().valueChanged.connect(self.view.scrollH)
self.verticalScrollBar().valueChanged.connect(self.view.scrollV)
and the AltGraphicsView is like this :
class AltGraphicsView(QGraphicsView):
def __init__(self, scene, parent):
super().__init__(scene, parent)
self.parent = parent
self.setSceneRect(parent.rect())
# Transparent so that we see the text behind
transparentBrush = QBrush()
transparentBrush.setColor(QColor(255, 255, 255, 0))
self.setBackgroundBrush(transparentBrush)
self.viewport().setAutoFillBackground(False)
# Functions to connect the scrolling ... doesn't work
def scrollV(self, value):
self.verticalScrollBar().setValue(value)
self.viewport().scroll(0,-value)
self.invalidateScene()
def scrollH(self, value):
self.horizontalScrollBar().setValue(value)
self.scrollContentsBy(-value,0)
# Do not catch anything -> "function-transparent"
def dragEnterEvent(self, event):
self.parent.dragEnterEvent(event)
return True
#...
def wheelEvent(self, event):
self.parent.wheelEvent(event)
return True
When I do not set self.setSceneRect(parent.rect()), the view is the size of Hello world at the top-left of the editor, but the scrolling works (must debug, but works a bit). When I set it, the view has a correct size... but does not scroll with the editor.
I think there's a problem with the size of the QGraphicsScene, but when I tried giving it a larger size than the QGraphicsView with self.graphicScene.setSceneRect(0,0,10000,10000), nothing changed (no scroll).
Does somebody has an idea about how to solve this scrolling problem?
----- new version -----------
Following musicamante's advice, I'm looking into the paintEvent function of QPlainTextEdit. Trying to understand how to draw the cursor so that it remains at the same place when scrolling.

scroll()and evenscrollContentsBy()on your own (the documentation of the latter also explicitly says that you should not use it to scroll programmatically). In theory, you should set the scene rect based on the extent of the scrollable area of the plain text edit, and also resize the view so that it fits the editor; in reality, embedding a QGraphicsView just to paint the cursor is completely inappropriate, other than an unnecessary complication. You should overridepaintEvent(), call the base implementation, and draw the cursor.setCursorWidth(), did you try it? If that's not what you want, are you trying to show a "block cursor" that includes the current character, similarly to some IDEs or terminals? In this case, this becomes an XY problem, which is asking the wrong question for the wrong problem.