Russian Qt Forum
Мая 24, 2025, 08:22 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QTextEdit и блоки текста  (Прочитано 9867 раз)
Rosster
Гость
« : Мая 24, 2012, 15:44 »

Всем привет, подскажите как можно реализовать следующую задачу:
Есть строка и нужно ее включить в QTextEdit:

this is text right, but this is text not right

Во-первых, если делать с помощью QTextBlock, то никак не могу достичь, чтобы они были в одной строке, а не каждый блок с новой строки.
Во-вторых, если пользователь вводит данные сразу после слова right, то текст печатается синим, а мне бы хотелось чтобы right был отдельным блоком и сразу после него печаталось обычным текстом,т.е. печатал уже в блоке ", but this is text "

Кто сможет помочь - ответьте.
Спасибо.
Записан
Bepec
Гость
« Ответ #1 : Мая 24, 2012, 15:50 »

Эм. По порядку.
1) каждый блок с новой строки - вы что-то делаете неправильно, вот оно и получается(% на 80 уверен). Код в студию, ваши попытки и способы обхода в студию.
2) Вот тут уже нужно изменять механизм блоков. Ибо вы сейчас хотите сделать выход из блока. Сами подумайте - по каким критериям вы сможете понять, что пользователь хочет напечатать синим, а по каким - не хочет.  Веселый
Записан
Rosster
Гость
« Ответ #2 : Мая 24, 2012, 16:20 »

Код:
QTextCursor cursor(textEdit->textCursor());
cursor.movePosition(QTextCursor::Start);

QTextCharFormat textFormat;
QTextCharFormat blueFormat;
blueFormat.setForeground(Qt::blue);

QTextCharFormat redFormat;
redFormat.setForeground(Qt::red);

cursor.insertText("this is text ", textFormat);
cursor.insertBlock();
cursor.insertText("right", blueFormat);
cursor.insertBlock();
cursor.insertText(", but this is text ", textFormat);
cursor.insertBlock();
cursor.insertText("not right", redFormat);

Получается все с новой строки.
Про второй вариант:
у меня задача такая: блоки right и not right пользователь не должен редактировать. Это я думаю смогу сделать с помощью восстановления текста через сигнал textChanged(). Но при этом пользователь должен спокойно писать до и после этих блоков. Вот в этом проблема.
Записан
Bepec
Гость
« Ответ #3 : Мая 24, 2012, 16:49 »

Если у тебя пользователь выделение текста не может(не имеет возможности), тогда тупо перекрашивай всё при любом изменении допустим.

Или же у тебя right /??? не статические, а изменяющиеся?
Записан
Rosster
Гость
« Ответ #4 : Мая 24, 2012, 21:57 »

Да да, именно так, я эти данные беру из БД и мне еще нужно в этих блоках как-то хранить их id (ищу ответа пока в инете).
Мне вот главное узнать как писать блоки слитно, а не с каждой строки.
Записан
vregess
Гость
« Ответ #5 : Мая 25, 2012, 09:13 »

Я думаю ты подошел не стой стороны.

Во-первых QTextBlock по определению это параграф. Так что каждый QTextBlock будет с новой строки.
Во-вторых, имхо, подсветку лучше сделать через QSyntaxHighlighter - в нем подсвечивать нужные элементы.

Как предлагаю сделать.
Для QTextBlock есть возможность устанавливать пользовательские данные: QTextBlock::setUserData(), QSyntaxHighlighter ::setCurrentBlockUserData().
Тебе нужно при каждом изменении блока парсить его содержание и сохранять результат в качестве user data для блока (тут же и твой id можно хранить).
Этот user data ты потом будешь использовать в QTextEdit, чтобы запретить редактирование.

Highlighter парсит текущий блок, создает нужные данные и заодно подсвечивает что надо.
Псевдокод:
Код
C++ (Qt)
...
void Highlighter::highlightBlock(const QString &text)
{
   BlockData *data = parseBlock(text);
   setFormat(data->rightStart, data->rightLen, rightFormat);
   setFormat(data->notRightStart, data->notRightLen, notRightFormat);
}
 
BockData* Highlighter::parseBlock(const QString &text)
{
   BlockData *data = new BlockData;
   ...
   setCurrentBlockUserData(data);
   return data;
}
 

А QTextEdit использует BlockData допустим в QTextEdit::keyPressEvent()
Псевдокод:
Код
C++ (Qt)
void MyTextEdit::keyPressEvent(QEvent *e)
{
   if (key pressed)
   {
       QTextCursor cur = textCursor();
       int cur_pos = cur.positionInBlock();
       BlockData *d = static_cast<BlockData*>(cur.block().userData());
       if (d)
       {
           // [1]  
       }
   }
 
   QTextEdit::keyPressEvent(e);
}
 

[1] - сверяешь позицию курсора с границами right и not right и делаешь e->ignore(), если надо запретить.

И, наверное, если ты работаешь просто с текстом, лучше использовать QPlainTextEdit вместо QTextEdit.
Как-то так.
Записан
Rosster
Гость
« Ответ #6 : Мая 25, 2012, 11:27 »

Спасибо, очень познавательно. Только, если считать, что я буду все писать в одном блоке (так как не могу использовать разные параграфы, текст и переменные со своим id должны быть на одной строке), то это будет гемор, я, например, не смогу хранить в setCurrentBlockUserData() id одной переменной, в этом блоке будет куча простого текста и переменных.
Может есть кроме QTextEdit еще какой-нить класс, чтобы блоки не разбивались на параграфы и разделялись между собой ем-то иным?
Записан
Bepec
Гость
« Ответ #7 : Мая 25, 2012, 12:00 »

хм. Может я неверно понимаю задачу, но почему бы вам не попробовать написать свой виджет с необходимыми вам функциями?
Записан
Rosster
Гость
« Ответ #8 : Мая 25, 2012, 12:17 »

Потому что мне нужны все функции и возможности присущие QTextEdit - копировать, вставка, возможность добавления QAction в меню и т.д.
Никак не могу понять, кому удобны будут блоки в виде параграфа, если это текстовый редактор. Кому надо писать так:
this is text
right
, but this is text
not right
Если можно написать слитно. Даже word визуально работает с блоками  Улыбающийся
В инете нашел инфу, где сказано: чтобы блоки не разделялись параграфами, нужно использовать QTextDocument с текстом в виде <p></p>. Но никаких примеров нету, и сам пробовал - не получилось.
Записан
vregess
Гость
« Ответ #9 : Мая 25, 2012, 12:56 »

Спасибо, очень познавательно. Только, если считать, что я буду все писать в одном блоке (так как не могу использовать разные параграфы, текст и переменные со своим id должны быть на одной строке), то это будет гемор, я, например, не смогу хранить в setCurrentBlockUserData() id одной переменной, в этом блоке будет куча простого текста и переменных.
Может есть кроме QTextEdit еще какой-нить класс, чтобы блоки не разбивались на параграфы и разделялись между собой ем-то иным?

Один блок или много блоков. Не вижу проблем. Тот же QSyntaxHighlighter используется и для QTextEdit (где много блоков) и для QLineEdit (где всего один блок).
Почему "не смогу хранить в setCurrentBlockUserData() id одной переменной"? можно хранить хоть десять id.
Почему бы во время парсинга не привязывать id к позиции в блоке?
Записан
Rosster
Гость
« Ответ #10 : Мая 25, 2012, 13:37 »

Цитировать
Почему бы во время парсинга не привязывать id к позиции в блоке?
Потому что пользователь может вводить текст куда хочет (кроме в переменную) и как хочет. Поэтому, естественно, позиция переменной, той же "right", уже изменится и неизвестно на какую величину. Если бы это все было статично, то проблем бы не было Улыбающийся
Записан
vregess
Гость
« Ответ #11 : Мая 25, 2012, 15:16 »

Потому что пользователь может вводить текст куда хочет (кроме в переменную) и как хочет. Поэтому, естественно, позиция переменной, той же "right", уже изменится и неизвестно на какую величину. Если бы это все было статично, то проблем бы не было Улыбающийся

Так для этого и делается
Код
C++ (Qt)
void Highlighter::highlightBlock(const QString &text)
{
   BlockData *data = parseBlock(text); // <-----
   ....
}
 

При каждом изменении текста будет создаваться новый user data с актуальными данными.
Записан
Rosster
Гость
« Ответ #12 : Мая 25, 2012, 16:10 »

Код
C++ (Qt)
void OmTextEdit::setMyText(QString text)
{
   QTextCursor cursor(this->textCursor());
   cursor.movePosition(QTextCursor::Start);
   cursor.insertText("this is text ");
   cursor.insertText("right");                          // [1]
   cursor.insertText(", but this is text");
}
 
Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
{
}
 
void Highlighter::highlightBlock(const QString &text)
{
   qDebug() << text;
   BlockData *data = parseBlock(text);
 
   //setFormat(data->rightStart, data->rightLen, rightFormat);
   //setFormat(data->notRightStart, data->notRightLen, notRightFormat);
}
 
BlockData* Highlighter::parseBlock(const QString &text)
{
   BlockData *data = new BlockData;
 
//    [2]
 
   setCurrentBlockUserData(data);
   return data;
}
 
[1] - здесь я знаю, что это переменная
[2] - откуда я узнаю rightStart и rightLen, если позиция все-время меняется
       а setCurrentBlockUserData присваивает текущему блоку, а блок то у нас один

Дебаг мне выведет:
this is text
this is text right                             //откуда я узнаю, что right - это переменная?Тем более если юзер нажал на букву
                                                  //сравнивать с предыдущим текстом?Тогда как?
this is text right, but this is text

Мне потом содержимое textEdit нужно взять обратно, чтобы занести это в БД, и естественно мне нужно знать где переменные, а где измененный текст, например перебором BlockData и если есть id, то это переменная.

Или я что-то не догоняю  Непонимающий Пятница все-таки. Если можно поподробней Улыбающийся
Записан
vregess
Гость
« Ответ #13 : Мая 26, 2012, 12:14 »

Откуда ты знаешь, что [1] - это переменная? По каким параметрам?
Записан
Rosster
Гость
« Ответ #14 : Мая 26, 2012, 17:13 »

ck, Надо было конечно мне с самого начала рассказать. Думал и так будет понятно.
У меня с БД приходит текст в виде шаблона, например: this is text <v>1</v>, but this is text <v>2</v>. Я его без проблем разбираю на части и вместо id подставляю переменные. Так как это шаблон, то пользователь, после вставки шаблона в textedit, дополняет и пишет что угодно. При этом сами переменные редактировать не может, только удалить или вставить новые (как это сделать я думаю сам догадаюсь). Ну а далее нужно этот текст уже измененный снова занести в БД. Мне хотя бы реализовать вставку нормальную, раскраску переменных.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 3.085 секунд. Запросов: 20.