Правильная отрисовка выделения текста в QTextDocument: использование QAbstractTextDocumentLayout::PaintContext

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Введение

Работа с текстом в Qt — это мощный, но иногда сложный процесс. Когда дело доходит до отрисовки выделения текста в QTextDocument, многие разработчики сталкиваются с проблемами. Часто предлагаемые решения, такие как изменение QTextCharFormat, не всегда подходят, особенно если нужно сохранить исходное форматирование текста. В этой статье я расскажу о правильном способе отрисовки выделения с использованием QAbstractTextDocumentLayout::PaintContext.

Почему стандартные методы не всегда работают

Обычно для выделения текста в QTextDocument используют QTextCursor и QTextCharFormat. Например:

QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);

QTextCharFormat format;
format.setBackground(Qt::yellow);
cursor.mergeCharFormat(format);

Этот метод изменяет форматирование текста, что не всегда удобно. Например, если вам нужно временно подсветить текст, а затем вернуть его в исходное состояние, этот подход потребует дополнительных усилий.

Правильный подход: использование QAbstractTextDocumentLayout::PaintContext

Для отрисовки выделения без изменения QTextCharFormat можно использовать QAbstractTextDocumentLayout::PaintContext. Этот метод позволяет отрисовать выделение текста, не изменяя его форматирование.

Как это работает

QAbstractTextDocumentLayout::PaintContext содержит информацию о том, как должен быть отрисован документ. В частности, он позволяет задать выделенные области (selections).

Пример кода

Вот как можно использовать PaintContext для отрисовки выделения:

#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QPainter>
#include <QTextCursor>

void drawTextDocumentWithSelection(QTextDocument* document, QPainter* painter, const QTextCursor& cursor) {
    // Создаем контекст отрисовки
    QAbstractTextDocumentLayout::PaintContext context;

    // Если есть выделение, добавляем его в контекст
    if (cursor.hasSelection()) {
        QTextCharFormat selectionFormat;
        selectionFormat.setBackground(Qt::blue); // Цвет подсветки
        selectionFormat.setForeground(Qt::white); // Цвет текста

        QAbstractTextDocumentLayout::Selection selection;
        selection.cursor = cursor;
        selection.format = selectionFormat;

        context.selections.append(selection);
    }

    // Отрисовываем документ с учетом контекста
    document->documentLayout()->draw(painter, context);
}

Как использовать

  1. Создайте QTextDocument и установите текст:

    QTextDocument document;
    document.setPlainText("Hello, this is a sample text.");
  2. Создайте QTextCursor и выделите текст:

    QTextCursor cursor(&document);
    cursor.movePosition(QTextCursor::Start);
    cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
  3. Отрисуйте документ с выделением:

    QPainter painter(this);
    drawTextDocumentWithSelection(&document, &painter, cursor);

Преимущества этого подхода

  1. Не изменяет форматирование текста: Выделение отрисовывается не затрагивая QTextCharFormat.

  2. Гибкость: Вы можете легко изменять цвет, прозрачность и другие параметры выделения.

  3. Производительность: Этот метод не требует изменения структуры документа, что делает его быстрым.

Заключение

Использование QAbstractTextDocumentLayout::PaintContext для отрисовки выделения текста в QTextDocument — это правильный и гибкий подход. Он позволяет отрисовать выделение без изменения форматирования текста и подходит для сложных сценариев, таких как подсветка синтаксиса или временное выделение.

Если вы работаете с QTextDocument и вам нужно отрисовать выделение, попробуйте этот метод. Он сэкономит вам время и упростит код.

P.S.
Статья целиком оформлена в DeepSeek. Мы вместе с ним довольно долго копались в QTextDocument, так что он точно передал мои мысли и идею, ведь в большинстве статей и форумных веток действительно предлагается вручную корежить данные самого документа для отрисовки выделения, но это в корне неверный и люто геморройный джуниорский подход. Я потратил пару дней на доскональное изучение исходников Qt, объяснил все DeepSeek, и попросил оформить это в хорошую и понятную статью. Так что не думайте, что он все сделал сам :) он только оформил:)

Источник: https://habr.com/ru/articles/881400/


Интересные статьи

Интересные статьи

Привет! Вероятно, тебе когда-нибудь попадались веб-приложения, построенные на «1С-Битрикс: Управление сайтом», и ты задавался вопросом: как это ломать? Вроде бы прошелся по всем известной методичке, н...
Привет, Хабр! Меня зовут Анастасия, я QA-специалист SimbirSoft и работаю на проектах с 1С-Битрикс. Не единожды я могла наблюдать, насколько эффективно бывает допустить QA-команду внутрь CMS, чтобы дос...
Вадим Гедзь, ведущий DevOps инженер, Dynatech Всем привет! Сегодня я хотел бы рассказать о том, как в компании, где я работаю, происходит переход к GitOps. В команде разработки больше 300 человек...
На Хабре ни для кого не секрет, что в текущей повестке практически все сферы частного бизнеса вынуждены реагировать на происходящие изменения. Большое количество привычных всем нам зарубежных сервисов...
Асинхронное программирование за последнее время стало не менее развитым направлением, чем классическое параллельное программирование, а в мире JavaSript, как в браузерах, так и в Node.js, поним...