Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Racheengel от Декабрь 05, 2006, 21:09



Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 05, 2006, 21:09
Сабж. QPainter::drawText довольно сильно тормозит. Есть ли возможность ускорить вывод текста?


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 05, 2006, 22:48
Убрать антиалиасинг, трансформацию, полупрозрачньІе цвета текста.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 06, 2006, 09:47
Упс, не указал выше - все и так выставлено по минимуму. Рисуется таблица, заполняются ячейки текстом. Если развернута на весь экран - одна отрисовка занимает до 400 мс. Тачка не медленная, Атлон 2500... Причем пофиг, выводишь ты 1 символ в ячейке или 10 - скорость одинаковая...


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: C.H. от Декабрь 06, 2006, 10:28
а ты сразу на экране рисуешь или в памяти а потом на экран??


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: crocus от Декабрь 06, 2006, 11:48
Не флейма ради:
В стандартном примере textedit есть принтпревью, так вот оно тоже очень тормозит-может реализация в самой библиотеке тормозная???


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: ElderOrb от Декабрь 06, 2006, 11:55
Можно попробовать воспользоваться QPainter-ом от QGLWidget-а. Иначе для чего существует void QPainter::setRedirected ? :) (Сам я так делать ни разу не пробовал, но где-то на форуме qtcenter.org проскакивала похожая мысль для ускорения отрисовки сложных виджэтов. )


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 06, 2006, 12:10
Неужели тормозит и в рилизной сборке?


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: crocus от Декабрь 06, 2006, 12:16
-static -release тормозит пендыр!!!


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Tonal от Декабрь 06, 2006, 12:57
Профилировать пробовал?
Точно тормозит именно drawText?
От видюхи не зависит?


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 06, 2006, 16:37
Не поверю, пока не увижу код. Откройте в Ассистанте какую-нибудь тяжёлую страницу и бьІстро мотайте её ползунком. Тормоза наблюдаете? И я нет. Значит дело не в скорости отрисовки текста, а в чём-то другом.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: crocus от Декабрь 06, 2006, 19:31
http://doc.trolltech.com/4.2/demos-textedit-printpreview-cpp.html

Попробуйте открыть в %QTDIR%\demos\textedit\release\textedit.exe любой документ .txt или .htm страниц на 20, откройте Print Preview и ,как вы говорите, просто помотайте ползунком туда-сюда  -  вы обалдеете от скорости.

И хотелось бы по этому вопросу узнать компетентное мнение nEoN !!!


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 06, 2006, 23:39
тормозит именно drawText, профилером смотрел. от видюхи не зависит.
ассистант - он же не текст печатает, а графику. т.е. все кеширует.
а у меня так низя :(


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 07, 2006, 00:53
Ассистант печатает не текст, а графику? А как вьІ обьясните динамическое изменение размеров окна Ассистанта? Конечно же происходит переразбиение структорированного текста, что и вьІзьІвает тормоза однократно. Но, в, вцелом, результат одинаковьІй - никаких тормозов при скроллировании текста, когда в drawText() подставляются готовьІе блоки.

Так что, дело не в рисовании текста, а в чём-то другом. Возможно есть прецендентьІ для проблем кеширования. Сам лично наблюдал тормоза при разбиении текста после изменения размеров текста Ассистанта (Cotrol + Скролл Вниз, потом Control + Скролл Вверх). Но само рисование работает на ура.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Tonal от Декабрь 07, 2006, 09:28
Цитата: "crocus"
http://doc.trolltech.com/4.2/demos-textedit-printpreview-cpp.html

Попробуйте открыть в %QTDIR%\demos\textedit\release\textedit.exe любой документ .txt или .htm страниц на 20, откройте Print Preview и ,как вы говорите, просто помотайте ползунком туда-сюда  -  вы обалдеете от скорости.

А ты в тот код заглядывал? ;-)
Они же там в paintEvent ВСЕ страницы полностью отрисовывают!
Понятно, что чем больше страниц, тем сильнее тормоза.
Тут любая система рисования загнётся. :-\
Можно элементарно вычислить, какие страницы должны отображаться и показывать только их.
В примере этим просто не озадачились - минус тролям (хотя и маленький ;) )


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 07, 2006, 15:28
Ассистант, он че делает - при ресайзе, заново все отрисовывает в кэш.
Это понятно, что потом работает быстро (при скроле). Но у меня проблема в том, что кэшировать нельзя - это таблица с кучей динамически изменяющихся данных. Т.е. каждые 50-100мс данные обновляются. А отрисовка занимает порядка 400-500мс на экран. Вот в чем лажа.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 07, 2006, 17:17
Цитата: "Racheengel"
Ассистант, он че делает - при ресайзе, заново все отрисовывает в кэш.
Это понятно, что потом работает быстро (при скроле).


Неужели вьІ думаете, что Ассистант рисует во внеекранньІй буфер страницу размером 400 кб, а потом просто бьІстро её блитит. Давайте прикинем, размер такого буфера получается должен исчисляться сотнями мегабайт, а время на его заполнение - десятками секунд при однократном ресайзе, смене шрифта. Кроме того забудем про гиперссьІлки, вьІделение текста мьІшью, поиск - ведь ето картинка.

Вам не кажется, что кеширование динамически изменяющихся частей по крайней мере глупо. Затем и придумали paintEvent().

Содержимое хранится в виде текста и каждьІй раз при скролле заново перерисовьІвается.

Есть множество других накладньІх расходов, связанньІх с рисованием, например, частая смена CompositionMode. То что задержка именно в drawText() может всего-лишь служить симптомом к реальной ошибке.

Сложно сказать в чём именно проблема, не видя код.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Tonal от Декабрь 07, 2006, 20:28
Цитата: "Racheengel"
Но у меня проблема в том, что кэшировать нельзя - это таблица с кучей динамически изменяющихся данных. Т.е. каждые 50-100мс данные обновляются. А отрисовка занимает порядка 400-500мс на экран.
И тебе надо постоянно перерисовывать ВСЮ таблицу?
Она ВСЯ одновременно отображается на экране?
Может быть всётаки можно ограничить подмножество того, что надо рисовать сейчас? И не пытаться перерисовать то, чего точно нет на экране?


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Вячеслав от Декабрь 07, 2006, 23:20
Таки может gl прикрутить ? на off-screen  рендеринг ? а рисовать только картинки ?


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 08, 2006, 01:25
Мне надо отображать часть таблицы, но если даже эта часть отображается в окне на весь экран - это самое окно с частью данных рисуется не особо быстро. Выводимые данные, естественно, фильтруются.

Код отрисовки - Он простой.

Цитировать

void QicsGrid::paintEvent ( QPaintEvent * event )
{
   QPainter p(this);

   p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing, false);

   p.setPen(Qt::black);
   p.setBrush(Qt::white);
   p.drawRect(event->rect());

   int row_from = m_rowOrigin;
   int rows_to_draw = rows();

   int col_from = m_colOrigin;
   int cols_to_draw = columns();

   int x = 0;
   int y = 0;

   m_rowsFit = m_colsFit = 0;

   for (int i = row_from; i < rows_to_draw; i++) {
      // if row hidden then continue
      if (rowVis()) continue;

      int row = rowOrder();
      int h = rowSize()[/*row*/i];
      x = 0;
      m_colsFit = 0;

      for (int j = col_from; j < cols_to_draw; j++) {
         // if col hidden then continue
         if (colVis()[j]) continue;

         int col = colOrder()[j];
         int w = colSize()[/*col*/j];
         
         QRect r(x,y,w,h);

         QicsCellItem *ci = cellItem(i, j);
         if (ci) {
            p.setPen(ci->colorForeGround);
            p.setBrush(ci->colorBackGround);
         } else {
            p.setPen(Qt::black);
            p.setBrush(Qt::white);
         }
         p.drawRect(r);

         QVariant v = data(row, col, i, j);
         if (v.isValid()) {
            p.drawText(r, Qt::AlignCenter, v.toString());
         }
         
         x += w;
         if (x >= width()) break;
         m_colsFit++;
      }

      y += h;
      if (y >= height()) break;
      m_rowsFit++;
   }

}


Тормозит в точке  p.drawText(r, Qt::AlignCenter, v.toString()).

добавлено спустя 5 минут:

 Возможно, трабла кроется в том, что у меня много вызовов drawText (в цикле) для отрисовки сравнительно малых порций текста... Но обойти это никак нельзя. Наверное, тормоза происходят даже не при отрисовке, а именно при предварительных расчетах/настройках и т.д. Печально, однака...


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 08, 2006, 14:01
Рисование белого фона текущей перерисовьІваемой части происходит неправильно: QPainter::drawRect() будет рисовать чёрньІе рамки где попало. Нужно юзать: p.setPen( Qt::NoPen ). Или, если рамка нужна на всё окно, - рисовать не drawRect( event->rect() ), а drawRect( rect() ) (QPainter сам соптимизирует заполнение цветом только текущего фрагмента из QPaintEvent).

Сразу бросается в глаза отсутствие проверки на пересечение текста и event->rect(). Проверка происходит где-то извне: rowVis(), colVis(). Естественно, что ети проверки вьІберут лишние фрагментьІ, которьІх сейча не видно. Как следствие - лишние вьІзовьІ drawText(). Тормоза из-за накладньІх расходов.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Tonal от Декабрь 08, 2006, 14:31
Вот в этом фрагменте:
Код:

QicsCellItem *ci = cellItem(i, j);
if (ci) {
  p.setPen(ci->colorForeGround);
  p.setBrush(ci->colorBackGround);
} else {
  p.setPen(Qt::black);
  p.setBrush(Qt::white);
}
p.drawRect(r);

QVariant v = data(row, col, i, j);
if (v.isValid()) {
  p.drawText(r, Qt::AlignCenter, v.toString());
}

Ты вызываешь QicsCellItem *ci = cellItem(i, j); и QVariant v = data(row, col, i, j);
Я бы это совместил - сделал в QicsCellItem функцию возвращающую сторку для отрисовки. ;-)
Кстати, в самом QicsCellItem можно и закешировать представление строки как QPixmap. И возвращать именно его.
Тогда, если одновременно изменяется относительно небольшое количество данных, должен получится существенный выигрыш.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 09, 2006, 00:04
Рамки - это как раз правильно (вокруг каждой ячейки рисуется черная рамка).

Не понимаю, что имеется в виду под отсутствием проверки на пересечение текста и event->rect(). event->rect() - это вся область, требующая перерисовки, т.е. размер viewport. Собственно, в эвенте и отрисовываются все ячейки, попавшие на экран.

rowVis(), colVis() - возвращают списки невидимых строк/столбцов. Они служат для определения того, какие строки/столбцы выключены пользователем (т.е. вообще не должны рисоваться).

Отрисока начинается с ячейки [m_rowOrigin, m_colOrigin] - т.е. она попадает в верхний левый угол. Далее, 2 цикла по строкам и по столбцам, которые итерируют только по ячейкам, попавшим в viewport (для этого происходит подсчет суммы ширины/высоты отрисованных ячеек, и когда это значение превышает размер видимой области - рисование в этом направлении прекращается).

Кэширование QPixmap делать пробовал. Но оно не помогает, если меняются одновременно ВСЕ ячейки, а наоборот, приводит к двойным тормозам и отжиранию памяти.

Кстати, если закомментить вызов drawText() - все летает (но контента ячеек не видно, естессно). Если же заставить выводить даже хотя бы один символ - все, дрова... Тормоза...


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Tonal от Декабрь 09, 2006, 11:33
Можно ещё схему кеширования придумать, например, если много значений совпадает, то кешируем не по ячейкам, а по значениям.
Строим QMap<QString, QPixmap>.
Если такой способ не канает, можно построить мап по всем символам, которые могут встречатся в значени, и собираем из них картинку - может получиться быстрее, хотя , думаю это то автоматом делается...

Да, что за задача такая?
И зачем эти значения отображать с такой частотой? Их же невозможно будет осознать!
Даже одно значение, не говоря уж о многих значениях в таблице на весь экран.
Может лучше как-нибудь по другому эту информацию отобразить?
Хотя-бы цветовыми градациями, а при наведении мышки, или выделении показывать собственно значение.

Иначе, даже если скорости ты добьешся, смысла в этом не будет. ;-)


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 09, 2006, 14:36
Цитата: "Racheengel"
Рамки - это как раз правильно (вокруг каждой ячейки рисуется черная рамка).


Имелось в виду, зачем делать в начале рисования:

Код:
p.setPen(Qt::black);
p.setBrush(Qt::white);
p.drawRect(event->rect());


Результат етого кода - чёрная рамка где попало. Но её не видно потому, что позже тьІ её закрашиваешь рамками для ячеек.

Цитата: "Racheengel"
Не понимаю, что имеется в виду под отсутствием проверки на пересечение текста и event->rect(). event->rect() - это вся область, требующая перерисовки, т.е. размер viewport. Собственно, в эвенте и отрисовываются все ячейки, попавшие на экран.


Не угадал. Viewport и текущая область рисования - разньІе вещи.

viewport != event->rect()

ОтрисовьІвать нужно только то, что попало в прямоугольник, записанньІй в класс собьІтия - ето оптимизация по скорости, для ето и придумали. Например, если нужно проскроллировать всего на несколько пикселей - прийдёт собьІтие, содержащее прямоугольний именно из етих пикселей, остальная часть просто скопируется подсистемой в другую часть екрана. ОбратньІй случай - если делается QPixmap::grabWidget() - в QPaintEvent попадёт прямоугольник, включающий даже области за пределами вьюпорта.

Ещё вопрос. А стандартньІе проги Qt у тебя как работают со скоростю рисования текста? Например Assistant с большой страницей.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Tonal от Декабрь 09, 2006, 16:14
Я так понял, что у Racheengel данные изменяются каждые 50 - 100мсек.
Причём он утверждает, что они ВСЕ изменяются.
И он делает repaint всей таблице.
Не совсем ясно, общее количество строк и столвцов на экране, но тут можно очень быстро до тормозов доехать.

Я бы лучше подумал, как изменить отображение, т.к. с описанной таблицей работать  почти не возможно...
Если это конечно на какой-то двумерный джек-пот, или цветомузыка.
Но тогда не ясно, зачем строки - можно цветами обойтись. ;-)


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 09, 2006, 16:25
Даже если данньІе изменяются 50 - 100 мс у Qt хватает можностей для отрисовки текста по всему екрану. Другой вопрос: на какого юзера рассчитано изменение большого количества текста на всём екране с частотой 10-20 раз в секунду? Даже в графическом представлении человек не способен уследить за большим количеством информации в реальном времени, разве что неспеша по логам.

Ещё можно обновлять по частям: QWidget::update( const QRect & rect ). Подсистема сама склеит области в один регион и отдаст вам его единождьІ в QPaintEvent'е.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 10, 2006, 20:57
Приложение - таблица для отображения биржевой активности.
Скоростьб обновления не устраивает клиента :(
Да и при скроле мышью притормаживает, неприятно.

Насчет viewport != event->rect() - у меня наблюдается как раз обратное. С каждым вызовом эвента viewport == event->rect()... (оно и логично - если весь экран обновляется).
Ассистант, зараза, быстро работает, это и обидно... Но с др. стороны - ассистант-то так часто не апдейтится...


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Dendy от Декабрь 10, 2006, 21:27
Если вьІложишь проект, которьІй возможно собрать и протестить самому - будеть идеально. А про viewport == event->rect() так ето просто частньІй случай. Правильно нужно делать как в теории, теория описана в документации.


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 11, 2006, 00:18
Могу выложить, куда?


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: cancroid от Декабрь 11, 2006, 14:51
Цитата: "Racheengel"
Могу выложить, куда?


Выложи на Лесной Базар или на Рапиду. А еще лучше - дай логин/пароль от ицэсовского SVN-а чтобы проще было скачать! Питэр будет в восторге!


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 12, 2006, 22:18
:)


Название: Qt 4.2 - QPainter::drawText, как ускорить?
Отправлено: Racheengel от Декабрь 25, 2006, 23:00
В общем - вроде дошел до пристойного решения - сделал кэш символов для каждого используемого фонта. В первый раз при выводе текста для каждого входящего в него символа создается монохромный битмап и суется в таблицу для соответствующего QFont. При отрисовке каждый символ берется из кэша, меняются цветовые атрибуты, и он выводится как картинка QImage. Проверил - реально в 2-3 раза быстрее, чем QPainter::drawText. Возможно, напишу статью про это.