#qt
Вопрос:
Возможно ли, чтобы QTextLayout отображал несколько символов, но обрабатывал/обрабатывал их как один символ. Например, отображение кодовой точки, такой как: [U 202e], и при перемещении курсора/вычислении позиций она обрабатывается как один символ.
Отредактированный:
Пожалуйста, проверьте эту следующую проблему, если я объясню, что я пытаюсь сделать. Это для компонента Qt edbee. Он использует QTextLayout для линейного рендеринга.
https://github.com/edbee/edbee-lib/issues/127
Возможно, это невозможно с QTextLayout, документация довольно ограничена.
Комментарии:
1. Я реализовал решение/обходной путь. Я завернул QTextLayout в свой собственный класс TextLayout, который выполняет вычисления виртуального курсора… (Для получения более подробной информации: github.com/edbee/edbee-lib/issues/128 )
Ответ №1:
Согласно документам Qt:
«Класс имеет довольно низкоуровневый API, и если вы не собираетесь реализовывать собственный рендеринг текста для какого — либо специализированного виджета, вам, вероятно, не потребуется использовать его напрямую». — https://doc.qt.io/qt-5/qtextlayout.html#details
Вероятно, вам следует использовать QLineEdit или QTextEdit (у каждого есть вызываемый метод setReadOnly(bool)
).
Прежде чем ответить на вопрос, я отмечу, что CursorMode
перечисление (https://doc.qt.io/qt-5/qtextlayout.html#CursorMode-enum) кажется очень многообещающим для этой проблемы, но, на мой взгляд, в документации неясно, как его использовать или настроить.
Теперь, чтобы ответить на ваш вопрос относительно QLineEdit или QTextEdit, это немного сложно, но это то же самое для QLineEdit и QTextEdit, поэтому давайте посмотрим на QTextEdit.
Во-первых, щелчки мыши: у QTextEdit есть вызванный сигнал cursorPositionChanged()
, который будет полезен здесь. Вы захотите подключить его к пользовательскому слоту, который может использовать эту функцию moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode = QTextCursor::MoveAnchor)
(https://doc.qt.io/qt-5/qtextedit.html#moveCursor). Обратите внимание, что здесь, в QTextCursor::MoveOperation, для вас есть очень полезные значения перечисления, касающиеся перехода по словам (https://doc.qt.io/qt-5/qtextcursor.html#MoveOperation-enum). Как нам собрать все это воедино? Что ж, вероятно, правильный способ сделать это-определить ширину символов слева от положения курсора и ширину символов справа от положения курсора при подаче cursorPositionChanged()
сигнала и перейти к стороне слова, которая имеет меньшую ширину. Однако я не уверен, как это сделать. На этом этапе я бы ограничился проверкой количества символов слева и справа и переходом в сторону с меньшим количеством.
Во-вторых, нажатия на клавиатуре: это немного выходит за рамки моих знаний, но почти все, что можно рисовать и выполнять, наследуется от QWidget. Взгляните на https://doc.qt.io/qt-5/qwidget.html#keyPressEvent и вполне возможно, что наиглавнейшее, что в вашей собственной реализации QTextEdit и надо чтобы стрелка влево и Стрелка вправо нажатий клавиш, чтобы перейти слов (как только вы получите, что это довольно просто, достаточно использовать одну и ту же функцию, как и в прошлом разделе, для перемещения курсора, или, в случае QLineEdit, cursorWordForward()
/ cursorWordBackward()
).
Все это, как говорится, я до сих пор предполагал, что вы ничего не удаляете и ничего не выбираете. Выбор может быть настоящей проблемой в зависимости от того, разрешаете ли вы несколько вариантов выбора, но в документации есть все функции для реализации этих вещей.
Пример внедрения щелчка мыши:
myclass.ГЭС
#include <QTextEdit>
#include <QTextCursor>
#include <QObject>
#include <QString>
int distance_to_word_beginning_or_end(const QString amp;str, int index, bool beginning);
class MyClass {
MyClass();
~MyClass();
private:
QTextEdit *text_edit;
public slots:
void text_edit_changed_cursor_location();
};
myclass.cpp
#include "myclass.hpp"
int distance_to_word_beginning_or_end(const QString amp;str, int index, bool beginning)
{
// return the distance from the beginning or end of the word from the index given
int inc_or_dec = (beginning) ? -1 : 1;
int distance = 0;
while (index >= 0 amp;amp; index < str.length())
{
if (str.at(index) == ' ' || str.at(index) == 'n' || str.at(index) == 't')
{
return distance;
}
distance ;
index = inc_or_dec;
}
return --distance;
}
MyClass::MyClass()
{
text_edit = new QTextEdit();
QObject::connect(text_edit, amp;QTextEdit::cursorPositionChanged, this, amp;MyClass::text_edit_changed_cursor_location);
}
MyClass::~MyClass()
{
delete text_edit;
}
void MyClass::text_edit_changed_cursor_location()
{
QString text_edit_string = text_edit->text();
QTextCursor text_edit_cursor = text_edit->textCursor();
auto current_position = text_edit_cursor.position();
QTextCursor new_text_cursor;
int distance_to_beginning = distance_to_word_beginning_or_end(text_edit_string, current_position, true);
int distance_to_end = distance_to_word_beginning_or_end(text_edit_string, current_position, false);
auto movement_type;
if (distance_to_beginning > distance_to_end)
{
new_text_cursor.setPosition(current_position distance_to_end);
} else {
new_text_cursor.setPosition(current_position - distance_to_beginning);
}
text_edit->setTextCursor(new_text_cursor);
}
Комментарии:
1. Было бы неплохо привести пример кода предлагаемого вами решения.
2. Ладно, я сделал это ради того, что, как я знал, сработало. Я его не компилировал, так что, если вы найдете в нем ошибки, не стесняйтесь их исправлять. Должно быть несколько понятно, что делает каждая часть
3. Где вы рассматриваете два символа как один?
4. @Catcow, спасибо за ваш подробный комментарий. Я немного расширил вопрос, чтобы стало ясно, что я действительно использую QTextLayout для специализированного виджета github.com/edbee/edbee-lib
5. Эй, извини, что это заняло некоторое время, и у меня не так много времени, чтобы разобраться во всем, но зацени это doc.qt.io/qt-5/qtextlayout.html#isValidCursorPosition это кажется очень похожим на то, что вы пытаетесь сделать здесь. Я буду продолжать искать ответы до тех пор, пока у меня будет время этим вечером