Struktur von Rich-Text-Dokumenten
Textdokumente werden durch die Klasse „ QTextDocument “ dargestellt, die Informationen über die interne Darstellung und Struktur des Dokuments enthält und Änderungen protokolliert, um Funktionen zum Rückgängigmachen und Wiederherstellen bereitzustellen.
Die strukturierte Darstellung eines Textdokuments präsentiert dessen Inhalt als Hierarchie aus Textblöcken, Rahmen, Tabellen und anderen Objekten. Diese verleihen dem Dokument eine logische Struktur und beschreiben, wie deren Inhalte angezeigt werden. Im Allgemeinen werden Rahmen und Tabellen verwendet, um andere Strukturen zu gruppieren, während Textblöcke die eigentlichen Textinformationen enthalten.
Neue Elemente werden programmgesteuert mit einem QTextCursor oder mithilfe eines Editor-Widgets, wie z. B. „ QTextEdit “, erstellt und in das Dokument eingefügt. Elementen kann bei ihrer Erstellung ein bestimmtes Format zugewiesen werden; andernfalls übernehmen sie das aktuelle Format des Cursors für das jeweilige Element.
![]() | Grundstruktur Die „oberste Ebene“ eines Dokuments könnte wie dargestellt aufgebaut sein. Jedes Dokument enthält immer einen Stamm-Frame, und dieser enthält immer mindestens einen Textblock. Bei Dokumenten mit Textinhalt enthält der Wurzelrahmen in der Regel eine Abfolge von Blöcken und anderen Elementen. Abfolgen von Rahmen und Tabellen werden in einem Dokument stets durch Textblöcke voneinander getrennt, auch wenn die Textblöcke keine Informationen enthalten. Dadurch wird sichergestellt, dass neue Elemente jederzeit zwischen bestehende Strukturen eingefügt werden können. |
In diesem Kapitel betrachten wir jedes der in einem Rich-Text-Dokument verwendeten Strukturelemente, beschreiben deren Eigenschaften und Verwendungszwecke und zeigen, wie man deren Inhalt untersucht. Die Dokumentbearbeitung wird im Abschnitt „Die QTextCursor-Schnittstelle“ beschrieben.
Rich-Text-Dokumente
QTextDocument Objekte enthalten alle Informationen, die zum Erstellen von Rich-Text-Dokumenten erforderlich sind. Auf Textdokumente kann auf zwei sich ergänzende Arten zugegriffen werden: als linearer Puffer für Editoren und als Objekthierarchie, die für Layout-Engines nützlich ist. Im hierarchischen Dokumentmodell entsprechen Objekte im Allgemeinen visuellen Elementen wie Rahmen, Tabellen und Listen. Auf einer tieferen Ebene beschreiben diese Elemente Eigenschaften wie den Textstil und die Ausrichtung. Die lineare Darstellung des Dokuments wird zur Bearbeitung und Manipulation des Dokumentinhalts verwendet.
Obwohl „ QTextEdit “ die Anzeige und Bearbeitung von Rich-Text-Inhalten vereinfacht, können Dokumente auch unabhängig von einem Editor-Widget verwendet werden, zum Beispiel:
QTextDocument *newDocument = new QTextDocument;Alternativ können sie aus einem bestehenden Editor extrahiert werden:
QTextEdit *editor = new QTextEdit;
QTextDocument *editorDocument = editor->document();Diese Flexibilität ermöglicht es Anwendungen, mehrere Rich-Text-Dokumente zu verarbeiten, ohne den Mehraufwand durch mehrere Editor-Widgets oder die Notwendigkeit, Dokumente in einem Zwischenformat zu speichern.
Ein leeres Dokument enthält einen Stammrahmen, der wiederum einen einzelnen leeren Textblock enthält. Rahmen sorgen für eine logische Trennung zwischen den Teilen des Dokuments, verfügen aber auch über Eigenschaften, die bestimmen, wie sie bei der Darstellung erscheinen. Eine Tabelle ist eine spezielle Art von Rahmen, die aus einer Reihe von Zellen besteht, die in Zeilen und Spalten angeordnet sind und jeweils weitere Strukturen und Text enthalten können. Tabellen bieten Verwaltungs- und Layoutfunktionen, mit denen sich flexible Zellkonfigurationen erstellen lassen.
Textblöcke enthalten Textfragmente, von denen jedes Informationen zur Text- und Zeichenformatierung angibt. Texteigenschaften werden sowohl auf Zeichenebene als auch auf Blockebene definiert. Auf Zeichenebene können Eigenschaften wie Schriftfamilie, Textfarbe und Schriftstärke festgelegt werden. Die Eigenschaften auf Blockebene steuern das übergeordnete Erscheinungsbild und Verhalten des Textes, wie beispielsweise die Textflussrichtung, die Ausrichtung und die Hintergrundfarbe.
Die Dokumentstruktur wird nicht direkt verändert. Die Bearbeitung erfolgt über eine cursorbasierte Oberfläche. Die Textcursor-Oberfläche fügt automatisch neue Dokumentelemente in den Wurzelrahmen ein und stellt sicher, dass dieser bei Bedarf mit leeren Blöcken aufgefüllt wird.
Den Stammrahmen erhalten wir auf folgende Weise:
QTextDocument *editorDocument = editor->document();
QTextFrame *root = editorDocument->rootFrame();Bei der Navigation durch die Dokumentstruktur ist es sinnvoll, beim Wurzelrahmen zu beginnen, da dieser Zugriff auf die gesamte Dokumentstruktur bietet.
Dokumentelemente
Rich-Text-Dokumente bestehen in der Regel aus gängigen Elementen wie Absätzen, Rahmen, Tabellen und Listen. Diese werden in einem „ QTextDocument “ durch die Klassen „ QTextBlock “, „ QTextFrame “, „ QTextTable “ und „ QTextList “ dargestellt. Im Gegensatz zu den anderen Elementen in einem Dokument werden Bilder durch speziell formatierte Textfragmente dargestellt. Dadurch können sie formatiert inline mit dem umgebenden Text platziert werden.
Die grundlegenden strukturellen Bausteine in Dokumenten sind „ QTextBlock “ und „ QTextFrame “. Blöcke selbst enthalten Rich-Text-Fragmente (QTextFragment), doch diese beeinflussen nicht direkt die übergeordnete Struktur eines Dokuments.
Elemente, die andere Dokumentelemente gruppieren können, sind in der Regel Unterklassen von „ QTextObject “ und lassen sich in zwei Kategorien einteilen: Elemente, die Textblöcke gruppieren, sind Unterklassen von „ QTextBlockGroup “, und solche, die Rahmen und andere Elemente gruppieren, sind Unterklassen von „ QTextFrame “.
Textblöcke
Textblöcke werden von der Klasse „ QTextBlock “ bereitgestellt.
Textblöcke fassen Textfragmente mit unterschiedlichen Zeichenformaten zusammen und dienen dazu, Absätze im Dokument darzustellen. Jeder Block enthält in der Regel eine Reihe von Textfragmenten mit unterschiedlichen Stilen. Fragmente werden erstellt, wenn Text in das Dokument eingefügt wird, und es kommen weitere hinzu, wenn das Dokument bearbeitet wird. Das Dokument teilt Fragmente auf, führt sie zusammen und entfernt sie, um die verschiedenen Textstile im Block effizient darzustellen.
Die Fragmente innerhalb eines bestimmten Blocks können mithilfe eines ` QTextBlock::iterator ` untersucht werden, um die interne Struktur des Blocks zu durchlaufen:
QTextBlock::iterator it;
for (it = currentBlock.begin(); !(it.atEnd()); ++it) {
QTextFragment currentFragment = it.fragment();
if (currentFragment.isValid())
processFragment(currentFragment);
}Blöcke werden auch zur Darstellung von Listenelementen verwendet. Daher können Blöcke eigene Zeichenformate definieren, die Informationen zur Formatierung auf Blockebene enthalten, wie beispielsweise die Art der für Listenelemente verwendeten Aufzählungszeichen. Die Formatierung des Blocks selbst wird durch die Klasse „ QTextBlockFormat “ beschrieben und umfasst Eigenschaften wie Textausrichtung, Einrückung und Hintergrundfarbe.
Auch wenn ein bestimmtes Dokument komplexe Strukturen enthalten mag, können wir, sobald wir einen Verweis auf einen gültigen Block im Dokument haben, in der Reihenfolge, in der sie geschrieben wurden, zwischen den einzelnen Textblöcken navigieren:
QTextBlock currentBlock = textDocument->begin();
while (currentBlock.isValid()) {
processBlock(currentBlock);
currentBlock = currentBlock.next();
}Diese Methode ist nützlich, wenn Sie nur den Rich-Text aus einem Dokument extrahieren möchten, da sie Rahmen, Tabellen und andere Strukturtypen ignoriert.
QTextBlock bietet Vergleichsoperatoren, die die Bearbeitung von Blöcken erleichtern: Mit ` operator==()` und ` operator!=()` wird geprüft, ob zwei Blöcke identisch sind, und mit ` operator<()` wird ermittelt, welcher Block in einem Dokument zuerst vorkommt.
Frames
Rahmen werden von der Klasse ` QTextFrame ` bereitgestellt.
Textrahmen fassen Textblöcke und untergeordnete Rahmen zusammen und bilden so Dokumentstrukturen, die größer sind als Absätze. Das Format eines Rahmens legt fest, wie er dargestellt und auf der Seite positioniert wird. Rahmen werden entweder in den Textfluss eingefügt oder schweben auf der linken oder rechten Seite der Seite. Jedes Dokument enthält einen Stammrahmen, der alle anderen Dokumentelemente enthält. Daher haben alle Rahmen außer dem Stammrahmen einen übergeordneten Rahmen.
Da Textblöcke zur Trennung anderer Dokumentelemente verwendet werden, enthält jeder Rahmen immer mindestens einen Textblock sowie null oder mehr untergeordnete Rahmen. Wir können den Inhalt eines Rahmens untersuchen, indem wir mithilfe eines „ QTextFrame::iterator “ die untergeordneten Elemente des Rahmens durchlaufen:
QTextFrame::iterator it;
for (it = frame->begin(); !(it.atEnd()); ++it) {
QTextFrame *childFrame = it.currentFrame();
QTextBlock childBlock = it.currentBlock();
if (childFrame)
processFrame(childFrame);
else if (childBlock.isValid())
processBlock(childBlock);
}Beachten Sie, dass der Iterator sowohl Rahmen als auch Blöcke auswählt; daher muss geprüft werden, auf welches Element er sich bezieht. Auf diese Weise können wir die Dokumentstruktur Rahmen für Rahmen durchlaufen und bei Bedarf dennoch auf Textblöcke zugreifen. Sowohl die Klasse „ QTextBlock::iterator “ als auch die Klasse „ QTextFrame::iterator “ können komplementär eingesetzt werden, um die gewünschte Struktur aus einem Dokument zu extrahieren.
Tabellen
Tabellen werden von der Klasse ` QTextTable ` bereitgestellt.
Tabellen sind Sammlungen von Zellen, die in Zeilen und Spalten angeordnet sind. Jede Tabellenzelle ist ein Dokumentelement mit eigener Zeichenformatierung, kann aber auch andere Elemente enthalten, wie beispielsweise Rahmen und Textblöcke. Tabellenzellen werden automatisch erstellt, wenn die Tabelle aufgebaut wird oder wenn zusätzliche Zeilen oder Spalten hinzugefügt werden. Sie können auch zwischen Tabellen verschoben werden.
QTextTable ist eine Unterklasse von ` QTextFrame`, daher werden Tabellen in der Dokumentstruktur wie Rahmen behandelt. Für jeden Rahmen, auf den wir im Dokument stoßen, können wir prüfen, ob er eine Tabelle darstellt, und ihn entsprechend anders behandeln:
QTextFrame::iterator it;
for (it = frame->begin(); !(it.atEnd()); ++it) {
QTextFrame *childFrame = it.currentFrame();
QTextBlock childBlock = it.currentBlock();
if (childFrame) {
QTextTable *childTable = qobject_cast<QTextTable*>(childFrame);
if (childTable)
processTable(childTable);
else
processFrame(childFrame);
} else if (childBlock.isValid()) {
processBlock(childBlock);
}
}Die Zellen innerhalb einer bestehenden Tabelle können durch Durchlaufen der Zeilen und Spalten untersucht werden.
for (int row = 0; row < table->rows(); ++row) {
for (int column = 0; column < table->columns(); ++column) {
QTextTableCell tableCell = table->cellAt(row, column);
processTableCell(tableCell);
}
}Listen
Listen werden von der Klasse ` QTextList ` bereitgestellt.
Listen sind Abfolgen von Textblöcken, die auf die übliche Weise formatiert sind, aber auch die Standard-Listendarstellungen wie Aufzählungszeichen und nummerierte Elemente bieten. Listen können verschachtelt werden und werden eingerückt, wenn das Listenformat eine Einrückung ungleich Null vorsieht.
Wir können jedes Listenelement anhand seines Index in der Liste referenzieren:
for (int index = 0; index < list->count(); ++index) {
QTextBlock listItem = list->item(index);
processListItem(listItem);
}Da ` QTextList ` eine Unterklasse von ` QTextBlockGroup` ist, gruppiert sie die Listenelemente nicht als untergeordnete Elemente, sondern stellt stattdessen verschiedene Funktionen zu deren Verwaltung bereit. Das bedeutet, dass jeder Textblock, auf den wir beim Durchlaufen eines Dokuments stoßen, tatsächlich ein Listenelement sein kann. Mit dem folgenden Code können wir sicherstellen, dass Listenelemente korrekt identifiziert werden:
QTextFrame::iterator it;
for (it = frame->begin(); !(it.atEnd()); ++it) {
QTextBlock block = it.currentBlock();
if (block.isValid()) {
QTextList *list = block.textList();
if (list) {
int index = list->itemNumber(block);
processListItem(list, index);
}
}
}Bilder
Bilder in „ QTextDocument “ werden durch Textfragmente dargestellt, die über den Ressourcenmechanismus auf externe Bilder verweisen. Bilder werden mithilfe der Cursor-Schnittstelle erstellt und können später durch Ändern des Zeichenformats des Textfragments des Bildes angepasst werden:
if (fragment.isValid()) {
QTextImageFormat newImageFormat = fragment.charFormat().toImageFormat();
if (newImageFormat.isValid()) {
newImageFormat.setName(":/images/newimage.png");
QTextCursor helper = cursor;
helper.setPosition(fragment.position());
helper.setPosition(fragment.position() + fragment.length(),
QTextCursor::KeepAnchor);
helper.setCharFormat(newImageFormat);
}
}Das Fragment, das das Bild darstellt, lässt sich durch Durchlaufen der Fragmente in dem Textblock finden, der das Bild enthält.
© 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.
