La interfaz QTextCursor
Los documentos se pueden editar a través de la interfaz proporcionada por la clase QTextCursor; los cursores se crean utilizando un constructor o se obtienen de un widget de editor. El cursor se utiliza para realizar operaciones de edición que se corresponden exactamente con las que el usuario es capaz de realizar por sí mismo en un editor. Como resultado, la información sobre la estructura del documento también está disponible a través del cursor, lo que permite modificar la estructura. El uso de una interfaz orientada al cursor para la edición hace que el proceso de escribir un editor personalizado sea más sencillo para los desarrolladores, ya que las operaciones de edición pueden visualizarse fácilmente.
La clase QTextCursor también mantiene información sobre cualquier texto que haya seleccionado en el documento, de nuevo siguiendo un modelo conceptualmente similar a las acciones realizadas por el usuario para seleccionar texto en un editor.
Los documentos de texto enriquecido pueden tener varios cursores asociados, y cada uno de ellos contiene información sobre su posición en el documento y las selecciones que pueda contener. Este paradigma basado en cursores hace que las operaciones comunes, como cortar y pegar texto, sean sencillas de implementar mediante programación, aunque también permite realizar operaciones de edición más complejas en el documento.
Este capítulo describe la mayoría de las operaciones de edición comunes que necesitará realizar utilizando un cursor, desde la inserción básica de texto y elementos del documento hasta la manipulación más compleja de las estructuras del documento.
Edición basada en el cursor
En el nivel más simple, los documentos de texto se componen de una cadena de caracteres, marcados de alguna manera para representar la estructura de bloques del texto dentro del documento. QTextCursor proporciona una interfaz basada en el cursor que permite manipular el contenido de un QTextDocument a nivel de caracteres. Dado que los elementos (bloques, marcos, tablas, etc.) también están codificados en el flujo de caracteres, el cursor puede modificar la estructura del documento.
El cursor no pierde de vista su ubicación dentro del documento principal y puede proporcionar información sobre la estructura circundante, como el bloque de texto, el marco, la tabla o la lista que lo rodea. Los formatos de las estructuras circundantes también pueden obtenerse directamente a través del cursor.
Utilización de un cursor
El cursor se utiliza principalmente para insertar o modificar texto dentro de un bloque. Para ello, podemos utilizar el cursor de un editor de texto:
QTextEdit *editor = new QTextEdit(); QTextCursor cursor(editor->textCursor());
Alternativamente, podemos obtener un cursor directamente de un documento:
QTextDocument *document = new QTextDocument(editor); QTextCursor cursor(document);
El cursor se sitúa al principio del documento para que podamos escribir en el primer bloque (vacío) del documento.
Agrupación de operaciones de cursor
Es posible agrupar una serie de operaciones de edición de modo que puedan repetirse o deshacerse juntas en una sola acción. Esto se consigue utilizando las funciones beginEditBlock() y endEditBlock() de la siguiente manera, como en el siguiente ejemplo en el que seleccionamos la palabra que contiene el cursor:
cursor.beginEditBlock(); cursor.movePosition(QTextCursor::StartOfWord); cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); cursor.endEditBlock();
Si no se agrupan las operaciones de edición, el documento registra automáticamente las operaciones individuales para poder deshacerlas posteriormente. Agrupar las operaciones en paquetes más grandes puede hacer que la edición sea más eficiente tanto para el usuario como para la aplicación, pero hay que tener cuidado de no agrupar demasiadas operaciones, ya que el usuario puede querer un control detallado sobre el proceso de deshacer.
Varios cursores
Pueden utilizarse varios cursores para editar simultáneamente el mismo documento, aunque sólo uno será visible para el usuario en un widget QTextEdit. QTextDocument garantiza que cada cursor escriba el texto correctamente y no interfiera con ninguno de los otros.
Inserción de elementos del documento
QTextCursor proporciona varias funciones que pueden utilizarse para cambiar la estructura de un documento de texto enriquecido. En general, estas funciones permiten crear elementos de documento con la información de formato pertinente, y se insertan en el documento en la posición del cursor.
El primer grupo de funciones inserta elementos a nivel de bloque y actualiza la posición del cursor, pero no devuelve el elemento insertado:
- insertBlock() inserta un nuevo bloque de texto (párrafo) en un documento en la posición del cursor, y mueve el cursor al comienzo del nuevo bloque.
- insertFragment() inserta un fragmento de texto existente en un documento en la posición del cursor.
- insertImage() inserta una imagen en un documento en la posición del cursor.
- insertText() inserta texto en el documento en la posición del cursor.
Puede examinar el contenido del elemento insertado a través de la interfaz del cursor.
El segundo grupo de funciones inserta elementos que estructuran el documento y devuelve la estructura insertada:
- insertFrame() inserta un marco en el documento después del bloque actual del cursor, y mueve el cursor al inicio del bloque vacío en el nuevo marco.
- insertList() inserta una lista en el documento en la posición del cursor, y mueve el cursor al inicio del primer elemento de la lista.
- insertTable() inserta una tabla en el documento después del bloque actual del cursor, y mueve el cursor al inicio del bloque que sigue a la tabla.
Estos elementos contienen o agrupan otros elementos del documento.
Texto y fragmentos de texto
El texto puede insertarse en el bloque actual en el formato de caracteres actual, o en un formato personalizado que se especifique con el texto:
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);
Una vez que se ha utilizado el formato de caracteres con un cursor, ese formato se convierte en el formato por defecto para cualquier texto que se inserte con ese cursor hasta que se especifique otro formato de caracteres.
Si se utiliza un cursor para insertar texto sin especificar un formato de caracteres, el texto recibirá el formato de caracteres utilizado en esa posición del documento.
Bloques
Los bloques de texto se insertan en el documento con la función insertBlock().
QTextBlockFormat backgroundFormat = blockFormat; backgroundFormat.setBackground(QColor("lightGray")); cursor.setBlockFormat(backgroundFormat);
El cursor se sitúa al principio del nuevo bloque.
Marcos
Los marcos se insertan en un documento utilizando el cursor, y se colocarán dentro del marco actual del cursor después del bloque actual. El siguiente código muestra cómo se puede insertar un marco entre dos bloques de texto en el marco raíz de un documento. Comenzamos encontrando el marco actual del cursor:
QTextFrame *mainFrame = cursor.currentFrame();
cursor.insertText(...);Insertamos algo de texto en este marco y luego establecemos un formato de marco para el marco hijo:
QTextFrameFormat frameFormat; frameFormat.setMargin(32); frameFormat.setPadding(8); frameFormat.setBorder(4);
El formato de marco dará al marco un margen externo de 32 píxeles, un relleno interno de 8 píxeles y un borde de 4 píxeles de ancho. Consulte la documentación de QTextFrameFormat para obtener más información sobre los formatos de marco.
El marco se inserta en el documento después del texto anterior:
cursor.insertFrame(frameFormat);
cursor.insertText(...);Añadimos texto al documento inmediatamente después de insertar el marco. Como el cursor de texto se sitúa dentro del marco cuando se inserta en el documento, este texto también se insertará dentro del marco.
Finalmente, posicionamos el cursor fuera del marco tomando la última posición disponible del cursor dentro del marco que grabamos anteriormente:
cursor = mainFrame->lastCursorPosition();
cursor.insertText(...);El texto que añadimos en último lugar se inserta después del marco hijo en el documento. Dado que cada marco se rellena con bloques de texto, esto garantiza que siempre se puedan insertar más elementos con el cursor.
Tablas
Las tablas se insertan en el documento utilizando el cursor, y se colocarán dentro del marco actual del cursor después del bloque actual:
QTextCursor cursor(editor->textCursor()); QTextTable *table = cursor.insertTable(rows, columns, tableFormat);
Las tablas pueden crearse con un formato específico que define las propiedades generales de la tabla, como su alineación, el color de fondo y el espaciado entre celdas utilizado. También puede determinar las restricciones de cada columna, permitiendo que cada una de ellas tenga una anchura fija, o que cambie de tamaño según el espacio disponible.
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);
Las columnas de la tabla creada anteriormente ocuparán cada una un determinado porcentaje de la anchura disponible. Tenga en cuenta que el formato de la tabla es opcional; si inserta una tabla sin formato, se utilizarán algunos valores por defecto razonables para las propiedades de la tabla.
Dado que las celdas pueden contener otros elementos del documento, también se les puede dar el formato y estilo necesarios.
Se puede añadir texto a la tabla desplazándose a cada celda con el cursor e insertando texto.
cell = table->cellAt(0, 0); cellCursor = cell.firstCursorPosition(); cellCursor.insertText(tr("Week"), charFormat);
Podemos crear un horario sencillo siguiendo este método:
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); } } }
Listas
Las listas de elementos de bloque pueden crearse automáticamente e insertarse en el documento en la posición actual del cursor. Cada lista creada de este modo requiere que se especifique un formato de lista:
QTextListFormat listFormat; if (list) { listFormat = list->format(); listFormat.setIndent(listFormat.indent() + 1); } listFormat.setStyle(QTextListFormat::ListDisc); cursor.insertList(listFormat);
El código anterior comprueba primero si el cursor está dentro de una lista existente y, en caso afirmativo, da al formato de lista para la nueva lista un nivel adecuado de sangría. Esto permite crear listas anidadas con niveles crecientes de sangría. Una implementación más sofisticada también utilizaría diferentes tipos de símbolos para las viñetas en cada nivel de la lista.
Imágenes
Las imágenes en línea se añaden a los documentos a través del cursor de la forma habitual. A diferencia de muchos otros elementos, todas las propiedades de las imágenes se especifican mediante el formato de la imagen. Esto significa que debe crearse un objeto QTextImageFormat antes de poder insertar una imagen:
QTextImageFormat imageFormat; imageFormat.setName(":/images/advert.png"); cursor.insertImage(imageFormat);
El nombre de la imagen hace referencia a una entrada del archivo de recursos de la aplicación. El método utilizado para obtener este nombre se describe en El sistema de recursos de Qt.
Ejemplos
El texto enriquecido se almacena en documentos de texto que pueden ser creados importando HTML desde una fuente externa, o generados usando QTextCursor.
Manipulación de texto enriquecido
La forma más sencilla de utilizar un documento de texto enriquecido es a través de la clase QTextEdit, que proporciona una vista editable sobre un documento. El siguiente código importa HTML en un documento, y muestra el documento utilizando un widget de edición de texto.
QTextEdit *editor = new QTextEdit(parent); editor->setHtml(aStringContainingHTMLtext); editor->show();
Puede recuperar el documento de la edición de texto utilizando la función document(). A continuación, el documento se puede editar mediante programación utilizando la clase QTextCursor. Esta clase sigue el modelo de un cursor de pantalla, y las operaciones de edición siguen la misma semántica. El siguiente código cambia la primera línea del documento a una fuente en negrita, dejando todas las demás propiedades de fuente intactas. El editor se actualizará automáticamente para reflejar los cambios realizados en los datos del documento subyacente.
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);
Observe que el cursor se movió desde el principio de la primera línea hasta el final, pero que conservó un ancla al principio de la línea. Esto demuestra las facilidades de selección basadas en el cursor de la clase QTextCursor.
Generar un calendario
El texto enriquecido puede generarse muy rápidamente utilizando el método basado en el cursor. El siguiente ejemplo muestra un calendario sencillo en un widget QTextEdit con encabezados en negrita para los días de la semana:
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); } }
El ejemplo anterior demuestra lo sencillo que es generar rápidamente nuevos documentos de texto enriquecido utilizando una cantidad mínima de código. Aunque hemos generado un calendario rudimentario de paso fijo para evitar citar demasiado código, Scribe proporciona características de diseño y formato mucho más sofisticadas.
© 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.