Интерфейс QTextCursorДокументы могут быть отредактированы через интерфейс, предоставленный классом QTextCursor; курсоры создаются с при помощи конструкторов или получают от виджетов-редакторов. Курсор используется для выполнения таких действий по редактированию, которые пользователь осуществляет сам, работая в редакторе. В результате информация о структуре документа также становится доступна и может быть изменена. Использование для редактирования интерфейса ориентированного на курсор делает для разработчиков более простым процесс написания пользовательского редактора, так как операции редактирования могут быть легко визуализированы. Класс QTextCursor также содержит информацию о выделенном в документе тексте и поддерживает возможности работы с выделенным текстом подобно возможностям работы пользователя в текстовом редакторе. Документы форматированного текста могут иметь несколько курсоров, связанных с ними и каждый из них содержит информацию о своей позиции в документе и любое выделение, которое он может содержать. Основанная на курсоре парадигма делает обычные операции, такие как вырезание и вставка текста, простыми для реализации программно и также позволяют выполнять в документе более сложные операции редактирования. Эта глава описывает большинства из общих операций редактирования которые вам потребуется выполнять используя курсор, от основных вставки текста и элементов документа до более сложных манипуляций со структурами документа. Редактирование, основанное на курсореНа простейшем уровне текстовые документы сделаны из строк символов, помеченных каким-либо образом для представления структуры блоков текста внутри документа. QTextCursor предоставляет основанный на курсоре интерфейс, который позволяет манипулировать содержимым QTextDocument на уровне символов. Так как элементы (блоки, фреймы, таблицы и так далее) также кодируются в потоку символов, структура документа может быть изменена курсором. Курсор отслеживает свое положение внутри родительского документа и может сообщать информацию об окружающей структуре, такой как обрамляющий текстовый блок, фрейм, таблица или список. Форматы обрамляющих структур могут быть также непосредственно получены через курсор. Использование курсораОсновное использование курсора это вставка или модифицирование текста внутри блока. Мы можем использовать курсор текстового редактора чтобы сделать это: QTextEdit *editor = new QTextEdit(); QTextCursor cursor(editor->textCursor()); Или же мы можем получить курсор прямо из документа: QTextDocument *document = new QTextDocument(editor); QTextCursor cursor(document); Курсор установлен в начале документа, так что мы можем писать в первый (пустой) блок в документе. Группирование операций курсораСерия операций редактирования может быть упакованы вместе, так что они могут быть повторены или отменены вместе в одно действие. Это достигается использованием функций beginEditBlock() и endEditBlock() следующим способом, как в следующем примере где мы выделяем слово которое содержит курсор: cursor.beginEditBlock(); cursor.movePosition(QTextCursor::StartOfWord); cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); cursor.endEditBlock(); Если операции редактирования не группируются, документ автоматически записывает индивидуальные записи так что они могут быть отменены позже. Группирование операций в большие пакеты может сделать редактирование более эффективным как для пользователя, так и для приложения, но надо позаботиться не группировать слишком много операций вместе так как пользователь может пожелать более скрупулёзный контроль над процессом отмены. Множественные курсорыМножественные курсоры могут быть использованы для одновременного редактирования одного документа, хотя только один будет виден пользователю в виджете QTextEdit. QTextDocument обеспечивает что каждый курсор пишет текст корректно и не мешает любому другому. Вставка элементов документаQTextCursor предоставляет несколько функций которые могут быть использованы для изменения структуры документа форматированного текста. В основном эти функции позволяют создавать элементы документа с важной информацией о форматировании и они могут быть вставлены в документ в позиции курсора. Первая группа функций вставляет элементы уровня блока и обновляет позицию курсора, но они не возвращают элемент, который был вставлен:
Вы можете исследовать содержимое элемента который был вставлен через интерфейс курсора. Вторая группа функций вставляет элементы которые предоставляют структуру документа и возвращают структуру которая была вставлена:
Эти элементы или содержат или группируют вместе элементы в документе. Текст и текстовые фрагментыТекст может быть вставлен в текущий блок и текущем формате символов или в собственном формате который указывается вместе с текстом: 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); После того как формат символов используется вместе с курсором он становится форматом по умолчанию для любого текста вставленного с этим курсором до тех пор пока не будет указан другой формат символов. Если курсор используется для вставки текста без указывания формата символов, то текст будет дан в формате символов, используемом в этой позиции в документе. БлокиТекстовые блоки вставляются в документ с функцией insertBlock(). QTextBlockFormat backgroundFormat = blockFormat; backgroundFormat.setBackground(QColor("lightGray")); cursor.setBlockFormat(backgroundFormat); Курсор устанавливается на начало нового блока. ФреймыФреймы вставляются в документ с использованием курсора и они будут размещены внутри текущего фрейма курсора после текущего блока. Следующий код показывает как фрейм может быть вставлен между двумя текстовыми блоками в корневом фрейме документа. Мы начинаем поиск текущего фрейма курсора: QTextFrame *mainFrame = cursor.currentFrame(); cursor.insertText(...); Мы вставляем некоторый текст в этот фрейм, затем мы устанавливаем формат фрейма для дочернего фрейма: QTextFrameFormat frameFormat; frameFormat.setMargin(32); frameFormat.setPadding(8); frameFormat.setBorder(4); Формат фрейма задаст фрейму дополнительный отступ на 32 пиксела, внутреннее наполнение на 8 пикселов и границу шириной 4 пиксела. Смотрите документацию по QTextFrameFormat для получения дополнительной информации о форматах фреймов. Фрейм вставляется в документ после предшествующего текста: cursor.insertFrame(frameFormat); cursor.insertText(...); Мы добавляем некоторый текст в документ сразу после вставки фрейма. Так как текстовый курсор устанавливается внутри фрейма когда он вставляется в документ, этот текст также будет вставлен внутри фрейма. Наконец, мы устанавливаем курсор снаружи фрейма беря последную доступную позицию курсора внутри фрейма которую мы записали ранее: cursor = mainFrame->lastCursorPosition(); cursor.insertText(...); Текст который мы добавили последним вставляется после дочернего фрейма в документе. Так как каждый фрейм заполняется текстовыми блоками, то это обеспечивает что дополнительные элементы всегда могут быть вставлены с помощью курсора. ТаблицыТаблицы вставляются в документ с использованием курсора и они будут размещены внутри текущего фрейма курсора после текущего блока. QTextCursor cursor(editor->textCursor()); QTextTable *table = cursor.insertTable(rows, columns, tableFormat); Таблицы могут быть созданы с указанным форматом который определяет все свойства таблицы, такие как её выравнивание, цвет фона и используемый интервал между ячейками. Он также может определить ограничения каждому столбца позволяя каждому из них иметь фиксированную величину или изменять размеры с соответствии с доступным пространством. QTextTableFormat tableFormat; tableFormat.setBackground(QColor("#e0e0e0")); QVector<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); Каждый из столбцов в таблице созданной выше возьмет определенный процент от доступной ширины. Заметьте, что формат таблицы необязателен; если вы вставите таблицу без формата то некоторые разумные значения по умолчанию будут использованы для параметров таблицы. Так как ячейки могут содержать другие элементы документа они также могут быть отформатированы и стилизированы при необходимости. Текст может быть добавлен в таблицу перемещением по каждой ячейке и вставкой текста. cell = table->cellAt(0, 0); cellCursor = cell.firstCursorPosition(); cellCursor.insertText(tr("Week"), charFormat); Мы можем создать простую временную диаграмму следующим подходом: 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); } } } СпискиСписки блоков элементов могут быть автоматически созданы и вставлены в документ в текущую позицию курсора. Каждый список который создан таким способом требует чтобы был указан формат списка: QTextListFormat listFormat; if (list) { listFormat = list->format(); listFormat.setIndent(listFormat.indent() + 1); } listFormat.setStyle(QTextListFormat::ListDisc); cursor.insertList(listFormat); Код выше сначала проверяет не стоит ли курсор внутри существующего списка или если да, то дает формату нового списка удобный уровень отступа. Это позволяет вложенным спискам создаваться с увеличенным уровнем отступа. Более изощренная реализация будет также использовать различные типы символов для точек на каждом уровне листа. ИзображенияВстроенные изображения добавляются в документ через курсор в обычном порядке. В отличае большинства других элементов все свойства изображения указываются форматом изображения. Это значит что объект QTextImageFormat должен быть создан прежде чем изображение может быть вставлено: QTextImageFormat imageFormat; imageFormat.setName(":/images/advert.png"); cursor.insertImage(imageFormat); Имя изображения ссылается на запись в файле ресурсов приложения. Метод используемый для наследования этого имени описан в Системе ресурсов Qt. ПримерыФорматированный текст хранится в текстовых документах, которые могут быть созданы импортированием HTML из внешних источников или созданы с помощью QTextCursor. Управление форматированным текстомСамый легкий способ использования форматированного текстового документа - это использование класса QTextEdit, обеспечивающего отображение и возможность редактирования документа. Код, приведённый ниже, импортирует документ HTML в текстовый документ и отображает текстовый документ в виджете, позволяющем редактировать текст. QTextEdit *editor = new QTextEdit(parent); editor->setHtml(aStringContainingHTMLtext); editor->show(); Вы можете получить указатель на текстовый документ от тестового редактора с помощью функции document(). После этого документ можно изменить программно, используя класс QTextCursor. Этот класс работает по принципу экранного курсора, а операции редактирования отображаются на экране. Следующий код изменяет начертание шрифта первой строки на полужирное, оставляя все другие характеристики нетронутыми. Редактор автоматически обновится для отображения сделанных изменений. 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); Обратите внимание на то, что курсор был перемещен от начала строки к концу и при этом сохранилась привязка к началу строки. Это показывает средства для работы с классом QTextCursor. Создание календаряИспользуя подход на основе курсора, можно очень быстро создать форматированный текст. Следующий пример отображает календарь в виджете QTextEdit с полужирными заголовками дней недели: editor = new QTextEdit(this); QTextCursor cursor(editor->textCursor()); cursor.movePosition(QTextCursor::Start); QTextCharFormat format(cursor.charFormat()); format.setFontFamily("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(QDate::shortDayName(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); } } Вышеприведенный пример демонстрирует, насколько просто создается форматированный текст и как мало для этого нужно кодировать. Хотя для минимизации кода мы отобразили простой неизменный календарь, Scribe предоставляет возможности более сложной компоновки и форматирования текста. |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |