Die QTextCursor-Schnittstelle
Dokumente können über die von der Klasse „ QTextCursor “ bereitgestellte Schnittstelle bearbeitet werden; Cursor werden entweder mithilfe eines Konstruktors erstellt oder von einem Editor-Widget abgerufen. Der Cursor dient zur Durchführung von Bearbeitungsvorgängen, die genau denen entsprechen, die der Benutzer selbst in einem Editor ausführen kann. Dadurch stehen über den Cursor auch Informationen zur Dokumentstruktur zur Verfügung, wodurch diese Struktur geändert werden kann. Die Verwendung einer cursororientierten Schnittstelle für die Bearbeitung vereinfacht Entwicklern das Schreiben eines benutzerdefinierten Editors, da sich die Bearbeitungsvorgänge leicht visualisieren lassen.
Die Klasse „ QTextCursor “ verwaltet zudem Informationen über den im Dokument ausgewählten Text und folgt dabei ebenfalls einem Modell, das konzeptionell den Aktionen ähnelt, mit denen der Benutzer in einem Editor Text auswählt.
Rich-Text-Dokumente können mit mehreren Cursorn verknüpft sein, und jeder dieser Cursor enthält Informationen über seine Position im Dokument sowie über etwaige Markierungen, die er enthält. Dieses cursorbasierte Paradigma macht gängige Vorgänge wie das Ausschneiden und Einfügen von Text einfach programmgesteuert umsetzbar, ermöglicht aber auch die Durchführung komplexerer Bearbeitungsvorgänge am Dokument.
Dieses Kapitel beschreibt die meisten gängigen Bearbeitungsvorgänge, die Sie mithilfe eines Cursors ausführen müssen – vom einfachen Einfügen von Text und Dokumentelementen bis hin zur komplexeren Bearbeitung von Dokumentstrukturen.
Cursorbasierte Bearbeitung
Auf der einfachsten Ebene bestehen Textdokumente aus einer Zeichenfolge, die auf bestimmte Weise markiert ist, um die Blockstruktur des Textes innerhalb des Dokuments darzustellen. „ QTextCursor “ bietet eine cursorbasierte Schnittstelle, die es ermöglicht, den Inhalt eines „ QTextDocument “ auf Zeichenebene zu bearbeiten. Da die Elemente (Blöcke, Rahmen, Tabellen usw.) ebenfalls im Zeichenstrom kodiert sind, kann die Dokumentstruktur selbst durch den Cursor verändert werden.
Der Cursor verfolgt seine Position innerhalb des übergeordneten Dokuments und kann Informationen über die umgebende Struktur melden, wie beispielsweise den umschließenden Textblock, Rahmen, die Tabelle oder die Liste. Die Formate der umschließenden Strukturen können ebenfalls direkt über den Cursor abgerufen werden.
Verwendung eines Cursors
Der Cursor dient in erster Linie dazu, Text innerhalb eines Blocks einzufügen oder zu ändern. Dazu können wir den Cursor eines Texteditors verwenden:
QTextEdit *editor = new QTextEdit();
QTextCursor cursor(editor->textCursor());Alternativ können wir einen Cursor direkt aus einem Dokument abrufen:
QTextDocument *document = new QTextDocument(editor);
QTextCursor cursor(document);Der Cursor wird am Anfang des Dokuments positioniert, sodass wir in den ersten (leeren) Block des Dokuments schreiben können.
Gruppieren von Cursor-Operationen
Eine Reihe von Bearbeitungsvorgängen kann gebündelt werden, sodass sie gemeinsam wiedergegeben oder in einem einzigen Schritt rückgängig gemacht werden können. Dies wird durch die Verwendung der Funktionen „ beginEditBlock() “ und „ endEditBlock() “ auf folgende Weise erreicht, wie im folgenden Beispiel, in dem wir das Wort auswählen, in dem sich der Cursor befindet:
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::StartOfWord);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
cursor.endEditBlock();Wenn Bearbeitungsvorgänge nicht gruppiert werden, zeichnet das Dokument die einzelnen Vorgänge automatisch auf, damit sie später rückgängig gemacht werden können. Das Gruppieren von Vorgängen zu größeren Einheiten kann die Bearbeitung sowohl für den Benutzer als auch für die Anwendung effizienter machen; es ist jedoch darauf zu achten, nicht zu viele Vorgänge zusammenzufassen, da der Benutzer möglicherweise eine fein abgestimmte Kontrolle über den Rückgängig-Vorgang wünscht.
Mehrere Cursor
Es können mehrere Cursor verwendet werden, um dasselbe Dokument gleichzeitig zu bearbeiten, obwohl für den Benutzer in einem „ QTextEdit “-Widget nur einer sichtbar ist. Das „ QTextDocument “ stellt sicher, dass jeder Cursor Text korrekt schreibt und die anderen nicht beeinträchtigt.
Einfügen von Dokumentelementen
QTextCursor bietet mehrere Funktionen, mit denen sich die Struktur eines Rich-Text-Dokuments ändern lässt. Im Allgemeinen ermöglichen diese Funktionen die Erstellung von Dokumentelementen mit den entsprechenden Formatierungsinformationen, die an der Cursorposition in das Dokument eingefügt werden.
Die erste Funktionsgruppe fügt Blockelemente ein und aktualisiert die Cursorposition, gibt jedoch das eingefügte Element nicht zurück:
- insertBlock() fügt einen neuen Textblock (Absatz) an der Cursorposition in ein Dokument ein und verschiebt den Cursor an den Anfang des neuen Blocks.
- insertFragment() fügt ein vorhandenes Textfragment an der Cursorposition in ein Dokument ein.
- insertImage() fügt an der Cursorposition ein Bild in ein Dokument ein.
- insertText() fügt Text an der Cursorposition in das Dokument ein.
Sie können den Inhalt des eingefügten Elements über die Cursor-Schnittstelle untersuchen.
Die zweite Funktionsgruppe fügt Elemente ein, die dem Dokument Struktur verleihen, und gibt die eingefügte Struktur zurück:
- insertFrame() fügt einen Rahmen in das Dokument hinter dem aktuellen Block des Cursors ein und bewegt den Cursor an den Anfang des leeren Blocks im neuen Rahmen.
- insertList() fügt an der Cursorposition eine Liste in das Dokument ein und bewegt den Cursor an den Anfang des ersten Elements in der Liste.
- insertTable() fügt eine Tabelle nach dem aktuellen Block des Cursors in das Dokument ein und bewegt den Cursor an den Anfang des Blocks, der auf die Tabelle folgt.
Diese Elemente enthalten entweder andere Elemente im Dokument oder fassen diese zusammen.
Text und Textfragmente
Text kann im aktuellen Block im aktuellen Zeichenformat oder in einem benutzerdefinierten Format eingefügt werden, das mit dem Text angegeben wird:
cursor.insertText(tr("Character formats"),
headingFormat);
cursor.insertBlock();
cursor.insertText(tr("Text can be displayed in a variety of "
"different character formats. "), plainFormat);
cursor.insertText(tr("We can emphasize text by "));
cursor.insertText(tr("making it italic"), emphasisFormat);Sobald das Zeichenformat mit einem Cursor verwendet wurde, wird dieses Format zum Standardformat für jeden mit diesem Cursor eingefügten Text, bis ein anderes Zeichenformat angegeben wird.
Wird ein Cursor zum Einfügen von Text verwendet, ohne ein Zeichenformat anzugeben, erhält der Text das Zeichenformat, das an dieser Position im Dokument verwendet wird.
Blöcke
Textblöcke werden mit der Funktion „ insertBlock “ () in das Dokument eingefügt.
QTextBlockFormat backgroundFormat = blockFormat;
backgroundFormat.setBackground(QColor("lightGray"));
cursor.setBlockFormat(backgroundFormat);Der Cursor wird am Anfang des neuen Blocks positioniert.
Rahmen
Rahmen werden mithilfe des Cursors in ein Dokument eingefügt und innerhalb des aktuellen Rahmens des Cursors hinter dem aktuellen Block platziert. Der folgende Code zeigt, wie ein Rahmen zwischen zwei Textblöcken im Stammrahmen eines Dokuments eingefügt werden kann. Zunächst ermitteln wir den aktuellen Rahmen des Cursors:
QTextFrame *mainFrame = cursor.currentFrame();
cursor.insertText(...);Wir fügen etwas Text in diesen Rahmen ein und legen dann ein Rahmenformat für den untergeordneten Rahmen fest:
QTextFrameFormat frameFormat;
frameFormat.setMargin(32);
frameFormat.setPadding(8);
frameFormat.setBorder(4);Das Rahmenformat weist dem Rahmen einen Außenrand von 32 Pixeln, einen Innenabstand von 8 Pixeln und einen 4 Pixel breiten Rahmen zu. Weitere Informationen zu Rahmenformaten finden Sie in der Dokumentation unter „ QTextFrameFormat “.
Der Rahmen wird nach dem vorangehenden Text in das Dokument eingefügt:
cursor.insertFrame(frameFormat);
cursor.insertText(...);Unmittelbar nach dem Einfügen des Rahmens fügen wir dem Dokument etwas Text hinzu. Da sich der Textcursor beim Einfügen des Rahmens in das Dokument innerhalb des Rahmens befindet, wird dieser Text ebenfalls innerhalb des Rahmens eingefügt.
Abschließend positionieren wir den Cursor außerhalb des Rahmens, indem wir die letzte verfügbare Cursorposition innerhalb des Rahmens verwenden, die wir zuvor gespeichert haben:
cursor = mainFrame->lastCursorPosition();
cursor.insertText(...);Der zuletzt hinzugefügte Text wird im Dokument hinter dem untergeordneten Rahmen eingefügt. Da jeder Rahmen mit Textblöcken aufgefüllt wird, stellt dies sicher, dass mit dem Cursor immer weitere Elemente eingefügt werden können.
Tabellen
Tabellen werden mithilfe des Cursors in das Dokument eingefügt und innerhalb des aktuellen Rahmens des Cursors nach dem aktuellen Block platziert:
QTextCursor cursor(editor->textCursor());
QTextTable *table = cursor.insertTable(rows, columns, tableFormat);Tabellen können mit einem bestimmten Format erstellt werden, das die allgemeinen Eigenschaften der Tabelle definiert, wie z. B. ihre Ausrichtung, Hintergrundfarbe und den verwendeten Zellenabstand. Es kann auch die Einschränkungen für jede Spalte festlegen, sodass jede Spalte entweder eine feste Breite haben oder sich entsprechend dem verfügbaren Platz anpassen kann.
QTextTableFormat tableFormat;
tableFormat.setBackground(QColor("#e0e0e0"));
QList<QTextLength> constraints;
constraints << QTextLength(QTextLength::PercentageLength, 16);
constraints << QTextLength(QTextLength::PercentageLength, 28);
constraints << QTextLength(QTextLength::PercentageLength, 28);
constraints << QTextLength(QTextLength::PercentageLength, 28);
tableFormat.setColumnWidthConstraints(constraints);
QTextTable *table = cursor.insertTable(rows, columns, tableFormat);Die Spalten in der oben erstellten Tabelle nehmen jeweils einen bestimmten Prozentsatz der verfügbaren Breite ein. Beachten Sie, dass das Tabellenformat optional ist; wenn Sie eine Tabelle ohne Format einfügen, werden für die Eigenschaften der Tabelle sinnvolle Standardwerte verwendet.
Da Zellen andere Dokumentelemente enthalten können, lassen auch diese nach Bedarf formatieren und stilistisch gestalten.
Text kann der Tabelle hinzugefügt werden, indem man mit dem Cursor zu jeder Zelle navigiert und dort Text einfügt.
cell = table->cellAt(0, 0);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(tr("Week"), charFormat);Mit diesem Ansatz können wir einen einfachen Stundenplan erstellen:
for (column = 1; column < columns; ++column) {
cell = table->cellAt(0, column);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(tr("Team %1").arg(column), charFormat);
}
for (row = 1; row < rows; ++row) {
cell = table->cellAt(row, 0);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(tr("%1").arg(row), charFormat);
for (column = 1; column < columns; ++column) {
if ((row-1) % 3 == column-1) {
cell = table->cellAt(row, column);
QTextCursor cellCursor = cell.firstCursorPosition();
cellCursor.insertText(tr("On duty"), charFormat);
}
}
}Listen
Listen aus Blockelementen können automatisch erstellt und an der aktuellen Cursorposition in das Dokument eingefügt werden. Für jede auf diese Weise erstellte Liste muss ein Listenformat angegeben werden:
QTextListFormat listFormat;
if (list) {
listFormat = list->format();
listFormat.setIndent(listFormat.indent() + 1);
}
listFormat.setStyle(QTextListFormat::ListDisc);
cursor.insertList(listFormat);Der obige Code prüft zunächst, ob sich der Cursor innerhalb einer bestehenden Liste befindet, und weist dem Listenformat der neuen Liste in diesem Fall eine passende Einrückungsebene zu. Auf diese Weise lassen sich verschachtelte Listen mit zunehmender Einrückungstiefe erstellen. Eine ausgefeiltere Implementierung würde zudem unterschiedliche Symbole für die Aufzählungspunkte in den einzelnen Ebenen der Liste verwenden.
Bilder
Inline-Bilder werden wie gewohnt über den Cursor in Dokumente eingefügt. Im Gegensatz zu vielen anderen Elementen werden alle Bildeigenschaften durch das Bildformat festgelegt. Das bedeutet, dass ein ` QTextImageFormat `-Objekt erstellt werden muss, bevor ein Bild eingefügt werden kann:
QTextImageFormat imageFormat;
imageFormat.setName(":/images/advert.png");
cursor.insertImage(imageFormat);Der Bildname bezieht sich auf einen Eintrag in der Ressourcendatei der Anwendung. Die Methode zur Ableitung dieses Namens wird im Abschnitt „Das Qt-Ressourcensystem“ beschrieben.
Beispiele
Rich-Text wird in Textdokumenten gespeichert, die entweder durch Importieren von HTML aus einer externen Quelle erstellt oder mithilfe eines ` QTextCursor` generiert werden können.
Bearbeitung von Rich-Text
Am einfachsten lässt sich ein Rich-Text-Dokument über die Klasse „ QTextEdit “ verwenden, die eine bearbeitbare Ansicht des Dokuments bereitstellt. Der folgende Code importiert HTML in ein Dokument und zeigt das Dokument mithilfe eines Textbearbeitungs-Widgets an.
QTextEdit *editor = new QTextEdit(parent);
editor->setHtml(aStringContainingHTMLtext);
editor->show();Mit der Funktion `document()` können Sie das Dokument aus dem Textbearbeitungs-Widget abrufen. Das Dokument lässt sich dann programmgesteuert mithilfe der Klasse ` QTextCursor ` bearbeiten. Diese Klasse ist einem Bildschirmcursor nachempfunden, und die Bearbeitungsvorgänge folgen derselben Semantik. Der folgende Code ändert die erste Zeile des Dokuments in eine fette Schriftart, während alle anderen Schriftarteneigenschaften unverändert bleiben. Der Editor wird automatisch aktualisiert, um die an den zugrunde liegenden Dokumentdaten vorgenommenen Änderungen widerzuspiegeln.
QTextDocument *document = edit->document();
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
QTextCharFormat format;
format.setFontWeight(QFont::Bold);
cursor.mergeCharFormat(format);Beachten Sie, dass der Cursor vom Anfang der ersten Zeile an das Ende verschoben wurde, dabei jedoch einen Anker am Zeilenanfang beibehalten hat. Dies veranschaulicht die cursorbasierten Auswahlfunktionen der Klasse ` QTextCursor `.
Erstellen eines Kalenders
Rich-Text lässt sich mithilfe des cursorbasierten Ansatzes sehr schnell generieren. Das folgende Beispiel zeigt einen einfachen Kalender in einem „ QTextEdit “-Widget mit fettgedruckten Überschriften für die Wochentage:
editor = new QTextEdit(this);
QTextCursor cursor(editor->textCursor());
cursor.movePosition(QTextCursor::Start);
QTextCharFormat format(cursor.charFormat());
format.setFontFamilies({"Courier"});
QTextCharFormat boldFormat = format;
boldFormat.setFontWeight(QFont::Bold);
cursor.insertBlock();
cursor.insertText(" ", boldFormat);
QDate date = QDate::currentDate();
int year = date.year(), month = date.month();
for (int weekDay = 1; weekDay <= 7; ++weekDay) {
cursor.insertText(QString("%1 ").arg(QLocale::system().dayName(weekDay), 3),
boldFormat);
}
cursor.insertBlock();
cursor.insertText(" ", format);
for (int column = 1; column < QDate(year, month, 1).dayOfWeek(); ++column) {
cursor.insertText(" ", format);
}
for (int day = 1; day <= date.daysInMonth(); ++day) {
int weekDay = QDate(year, month, day).dayOfWeek();
if (QDate(year, month, day) == date)
cursor.insertText(QString("%1 ").arg(day, 3), boldFormat);
else
cursor.insertText(QString("%1 ").arg(day, 3), format);
if (weekDay == 7) {
cursor.insertBlock();
cursor.insertText(" ", format);
}
}Das obige Beispiel zeigt, wie einfach es ist, mit minimalem Codeaufwand schnell neue Rich-Text-Dokumente zu erstellen. Obwohl wir einen einfachen Kalender mit fester Zeichenbreite erstellt haben, um nicht zu viel Code anzuführen, bietet Scribe weitaus ausgefeiltere Layout- und Formatierungsfunktionen.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.