En esta página

Estructura de un documento de texto enriquecido

Los documentos de texto están representados por la clase QTextDocument, que contiene información sobre la representación interna del documento, su estructura, y realiza un seguimiento de las modificaciones para proporcionar facilidades de deshacer/rehacer.

La representación estructurada de un documento de texto presenta su contenido como una jerarquía de bloques de texto, marcos, tablas y otros objetos. Éstos proporcionan una estructura lógica al documento y describen cómo se mostrará su contenido. Por lo general, los marcos y las tablas se utilizan para agrupar otras estructuras, mientras que los bloques de texto contienen la información textual propiamente dicha.

Los nuevos elementos se crean e insertan en el documento mediante programación con un QTextCursor o utilizando un widget del editor, como QTextEdit. A los elementos se les puede dar un formato particular cuando se crean; de lo contrario toman el formato actual del cursor para el elemento.

Estructura básica

El "nivel superior" de un documento puede estar poblado de la forma que se muestra. Cada documento siempre contiene un marco raíz, y éste siempre contiene al menos un bloque de texto.

En los documentos con algún contenido textual, el marco raíz suele contener una secuencia de bloques y otros elementos.

Las secuencias de marcos y tablas siempre están separadas por bloques de texto en un documento, aunque los bloques de texto no contengan información. Esto garantiza que siempre puedan insertarse nuevos elementos entre las estructuras existentes.

En este capítulo, veremos cada uno de los elementos estructurales utilizados en un documento de texto enriquecido, describiremos sus características y usos, y mostraremos cómo examinar su contenido. La edición de documentos se describe en La interfaz QTextCursor.

Documentos de texto enriquecido

QTextDocument contienen toda la información necesaria para construir documentos de texto enriquecido. Se puede acceder a los documentos de texto de dos formas complementarias: como un buffer lineal para uso de los editores, y como una jerarquía de objetos útil para los motores de maquetación. En el modelo jerárquico de documentos, los objetos suelen corresponder a elementos visuales como marcos, tablas y listas. En un nivel inferior, estos elementos describen propiedades como el estilo y la alineación del texto. La representación lineal del documento se utiliza para editar y manipular su contenido.

Aunque QTextEdit facilita la visualización y edición de texto enriquecido, los documentos también pueden utilizarse independientemente de cualquier widget editor, por ejemplo:

QTextDocument *newDocument = new QTextDocument;

También pueden extraerse de un editor existente:

QTextEdit *editor = new QTextEdit;
QTextDocument *editorDocument = editor->document();

Esta flexibilidad permite a las aplicaciones manejar múltiples documentos de texto enriquecido sin la sobrecarga de múltiples widgets de edición, o requerir que los documentos se almacenen en algún formato intermedio.

Un documento vacío contiene un marco raíz que, a su vez, contiene un único bloque de texto vacío. Los marcos proporcionan una separación lógica entre las partes del documento, pero también tienen propiedades que determinan cómo aparecerán cuando se visualicen. Una tabla es un tipo especializado de marco que consiste en un número de celdas, organizadas en filas y columnas, cada una de las cuales puede contener más estructura y texto. Las tablas ofrecen funciones de gestión y diseño que permiten crear configuraciones flexibles de celdas.

Los bloques de texto contienen fragmentos de texto, cada uno de los cuales especifica información sobre el texto y el formato de los caracteres. Las propiedades textuales se definen tanto a nivel de carácter como de bloque. A nivel de carácter, pueden especificarse propiedades como la familia de fuentes, el color del texto y el peso de la fuente. Las propiedades a nivel de bloque controlan la apariencia y el comportamiento del texto a un nivel superior, como la dirección del flujo de texto, la alineación y el color de fondo.

La estructura del documento no se manipula directamente. La edición se realiza a través de una interfaz basada en el cursor. La interfaz del cursor de texto inserta automáticamente nuevos elementos del documento en el marco raíz y se asegura de que se rellene con bloques vacíos cuando sea necesario.

Obtenemos el marco raíz de la siguiente manera:

    QTextDocument *editorDocument = editor->document();
    QTextFrame *root = editorDocument->rootFrame();

Cuando se navega por la estructura del documento, es útil comenzar por el marco raíz, ya que proporciona acceso a toda la estructura del documento.

Elementos del documento

Los documentos de texto enriquecido suelen constar de elementos comunes como párrafos, marcos, tablas y listas. Estos elementos están representados en QTextDocument por las clases QTextBlock, QTextFrame, QTextTable, y QTextList. A diferencia de los demás elementos de un documento, las imágenes se representan mediante fragmentos de texto especialmente formateados. Esto les permite colocarse en línea con el texto que las rodea.

Los bloques estructurales básicos de los documentos son QTextBlock y QTextFrame. Los propios bloques contienen fragmentos de texto enriquecido (QTextFragment), pero éstos no influyen directamente en la estructura de alto nivel de un documento.

Los elementos que pueden agrupar otros elementos del documento suelen ser subclases de QTextObject, y se dividen en dos categorías: Los elementos que agrupan bloques de texto son subclases de QTextBlockGroup, y los que agrupan marcos y otros elementos son subclases de QTextFrame.

Bloques de texto

La clase QTextBlock proporciona bloques de texto.

Los bloques de texto agrupan fragmentos de texto con distintos formatos de caracteres y se utilizan para representar párrafos en el documento. Cada bloque suele contener varios fragmentos de texto con estilos diferentes. Los fragmentos se crean cuando se inserta texto en el documento, y se añaden más cuando se edita el documento. El documento divide, fusiona y elimina fragmentos para representar eficazmente los distintos estilos de texto del bloque.

Los fragmentos de un bloque determinado pueden examinarse utilizando QTextBlock::iterator para recorrer la estructura interna del bloque:

    QTextBlock::iterator it;
    for (it = currentBlock.begin(); !(it.atEnd()); ++it) {
        QTextFragment currentFragment = it.fragment();
        if (currentFragment.isValid())
            processFragment(currentFragment);
    }

Los bloques también se utilizan para representar elementos de listas. En consecuencia, los bloques pueden definir sus propios formatos de caracteres, que contienen información sobre la decoración a nivel de bloque, como el tipo de viñetas utilizadas para los elementos de lista. El formato del propio bloque se describe mediante la clase QTextBlockFormat, y describe propiedades como la alineación del texto, la sangría y el color de fondo.

Aunque un documento dado puede contener estructuras complejas, una vez que tenemos una referencia a un bloque válido en el documento, podemos navegar entre cada uno de los bloques de texto en el orden en que fueron escritos:

    QTextBlock currentBlock = textDocument->begin();

    while (currentBlock.isValid()) {
        processBlock(currentBlock);
        currentBlock = currentBlock.next();
    }

Este método es útil cuando se desea extraer sólo el texto enriquecido de un documento, ya que ignora marcos, tablas y otros tipos de estructura.

QTextBlock proporciona operadores de comparación que facilitan la manipulación de los bloques: operator==() y operator!=() se utilizan para comprobar si dos bloques son iguales, y operator<() sirve para determinar cuál aparece primero en un documento.

Marcos

La clase QTextFrame proporciona los marcos.

Los marcos de texto agrupan bloques de texto y marcos hijos, creando estructuras de documento mayores que los párrafos. El formato de un marco especifica cómo se representa y posiciona en la página. Los marcos se insertan en el flujo de texto o flotan a la izquierda o a la derecha de la página. Cada documento contiene un marco raíz que contiene todos los demás elementos del documento. Por consiguiente, todos los marcos, excepto el marco raíz, tienen un marco padre.

Dado que los bloques de texto se utilizan para separar otros elementos del documento, cada marco siempre contendrá al menos un bloque de texto, y cero o más marcos hijos. Podemos inspeccionar el contenido de un marco utilizando un QTextFrame::iterator para recorrer los elementos hijos del marco:

    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);
    }

Observe que el iterador selecciona tanto marcos como bloques, por lo que es necesario comprobar a cuál se refiere. Esto nos permite navegar por la estructura del documento fotograma a fotograma y, al mismo tiempo, acceder a los bloques de texto si es necesario. Las clases QTextBlock::iterator y QTextFrame::iterator pueden utilizarse de forma complementaria para extraer la estructura necesaria de un documento.

Tablas

La clase QTextTable proporciona tablas.

Las tablas son colecciones de celdas dispuestas en filas y columnas. Cada celda de la tabla es un elemento del documento con su propio formato de caracteres, pero también puede contener otros elementos, como marcos y bloques de texto. Las celdas de tabla se crean automáticamente cuando se construye la tabla, o cuando se añaden filas o columnas adicionales. También pueden moverse entre tablas.

QTextTable es una subclase de QTextFrame, por lo que las tablas se tratan como marcos en la estructura del documento. Para cada marco que encontremos en el documento, podemos comprobar si representa una tabla y tratarlo de una manera diferente:

    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);
        }
    }

Las celdas dentro de una tabla existente pueden examinarse iterando a través de las filas y columnas.

    for (int row = 0; row < table->rows(); ++row) {
        for (int column = 0; column < table->columns(); ++column) {
            QTextTableCell tableCell = table->cellAt(row, column);
            processTableCell(tableCell);
        }
    }

Listas

La clase QTextList proporciona listas.

Las listas son secuencias de bloques de texto que se formatean de la manera habitual, pero que también proporcionan las decoraciones estándar de las listas, como viñetas y elementos enumerados. Las listas pueden anidarse y se sangrarán si el formato de la lista especifica una sangría distinta de cero.

Podemos referirnos a cada elemento de la lista por su índice en la lista:

    for (int index = 0; index < list->count(); ++index) {
        QTextBlock listItem = list->item(index);
        processListItem(listItem);
    }

Dado que QTextList es una subclase de QTextBlockGroup, no agrupa los elementos de la lista como elementos hijos, sino que proporciona varias funciones para gestionarlos. Esto significa que cualquier bloque de texto que encontremos al recorrer un documento puede ser en realidad un elemento de lista. Podemos asegurarnos de que los elementos de la lista se identifican correctamente utilizando el siguiente código:

    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);
            }
        }
    }

Imágenes

Las imágenes en QTextDocument se representan mediante fragmentos de texto que hacen referencia a imágenes externas a través del mecanismo de recursos. Las imágenes se crean utilizando la interfaz de cursor, y pueden modificarse posteriormente cambiando el formato de caracteres del fragmento de texto de la imagen:

    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);
        }
    }

El fragmento que representa la imagen puede encontrarse iterando sobre los fragmentos del bloque de texto que contiene la imagen.

© 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.