QML TextEdit get current cursor position
-
wrote on 4 Sept 2024, 11:56 last edited by
I am trying to get cursor row and column in the TextEdit control so I can put that information in the status bar (footer). I am trying to use QTextCursor as I would in Qt Widgets but in my Python slot (CharCounter.cursor.position) I always get 0, 0, as the position
view.qml
import QtQuick import QtQuick.Controls import QtQuick.Layouts import examples.charcounter ApplicationWindow { visible: true width: 400 height:200 title: "Template App" CharCounter { id: charCounter } RowLayout { anchors.fill: parent TextArea { id: textArea text: "Hello Qml!" Layout.fillWidth: true Layout.fillHeight: true onTextChanged: { charCounter.cursor_position(textDocument) } } } footer: RowLayout { Label { id: statusLabel } } }
import sys from PySide6.QtGui import QGuiApplication, QTextDocument, QTextCursor from PySide6.QtQml import QQmlApplicationEngine, QmlElement from PySide6.QtCore import QObject, Slot from PySide6.QtQuick import QQuickTextDocument QML_IMPORT_NAME = 'examples.charcounter' QML_IMPORT_MAJOR_VERSION = 1 @QmlElement class CharCounter(QObject): def __init__(self, parent=None): super().__init__(parent) @Slot(QQuickTextDocument) def cursor_position(self, textDocument): #print(textDocument.textDocument().toPlainText()) cursor = QTextCursor(textDocument.textDocument()) print(cursor.blockNumber(), cursor.columnNumber()) if __name__ == '__main__': app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.quit.connect(app.quit) engine.load('view.qml') result = app.exec() del engine sys.exit(result)
-
wrote on 4 Sept 2024, 14:17 last edited by
I see what you are trying to do but I think the issue is that you are creating a new cursor that, according to the documentation, will initialise itself at position (0, 0) of the document. There is no intrinsic cursor position stored in the document itself that the new cursor will acquire.
Meanwhile, presumably the internals of the QML code has its own cursor object that knows where it is within the document.
As for what you want to achieve, I'm afraid I don't see an obvious way to do it. But I am not an expert and maybe someone else will be able to suggest something.
-
I see what you are trying to do but I think the issue is that you are creating a new cursor that, according to the documentation, will initialise itself at position (0, 0) of the document. There is no intrinsic cursor position stored in the document itself that the new cursor will acquire.
Meanwhile, presumably the internals of the QML code has its own cursor object that knows where it is within the document.
As for what you want to achieve, I'm afraid I don't see an obvious way to do it. But I am not an expert and maybe someone else will be able to suggest something.
wrote on 4 Sept 2024, 15:50 last edited by@Bob64 Hey thanks! I actually got it to work using TextArea.cursorPosition. Turns out QTextCursor has a setPosition() method so I just set the cursor position immediately after creating it. On the Qml side I had to use onCursorPositionChanged instead of onTextChanged so the label is updated on cursor movement. Here is the full code for reference
import sys from PySide6.QtGui import QGuiApplication, QTextCursor from PySide6.QtQml import QQmlApplicationEngine, QmlElement from PySide6.QtCore import QObject, Slot from PySide6.QtQuick import QQuickTextDocument QML_IMPORT_NAME = 'examples.charcounter' QML_IMPORT_MAJOR_VERSION = 1 @QmlElement class CharCounter(QObject): def __init__(self, parent=None): super().__init__(parent) @Slot(QQuickTextDocument, int, result=list) def cursor_position(self, textDocument, cursorPosition): cursor = QTextCursor(textDocument.textDocument()) cursor.setPosition(cursorPosition) return (cursor.blockNumber(), cursor.columnNumber()) if __name__ == '__main__': app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.quit.connect(app.quit) engine.load('view.qml') result = app.exec() del engine sys.exit(result)
view.qml
import QtQuick import QtQuick.Controls import QtQuick.Layouts import examples.charcounter ApplicationWindow { visible: true width: 400 height:200 title: "Template App" CharCounter { id: charCounter } RowLayout { anchors.fill: parent TextArea { id: textArea text: "Hello Qml!" Layout.fillWidth: true Layout.fillHeight: true onCursorPositionChanged: { let [row, col] = charCounter.cursor_position( textDocument, cursorPosition) statusLabel.text = "row: " + row + ", col: " + col } } } footer: RowLayout { Label { id: statusLabel } } }
-
-
wrote on 5 Sept 2024, 08:26 last edited by
I had seen the
cursorPosition
property but I couldn't see a way to translate that into a row and column position in the document. Your solution seems to do that. Nice!
1/4