Russian Qt Forum
Сентябрь 30, 2024, 10:31 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: Qt 4.2 - QPainter::drawText, как ускорить?  (Прочитано 21260 раз)
Dendy
Гость
« Ответ #15 : Декабрь 07, 2006, 17:17 »

Цитата: "Racheengel"
Ассистант, он че делает - при ресайзе, заново все отрисовывает в кэш.
Это понятно, что потом работает быстро (при скроле).


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

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

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

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

Сложно сказать в чём именно проблема, не видя код.
Записан
Tonal
Гость
« Ответ #16 : Декабрь 07, 2006, 20:28 »

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

Таки может gl прикрутить ? на off-screen  рендеринг ? а рисовать только картинки ?
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #18 : Декабрь 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 (в цикле) для отрисовки сравнительно малых порций текста... Но обойти это никак нельзя. Наверное, тормоза происходят даже не при отрисовке, а именно при предварительных расчетах/настройках и т.д. Печально, однака...
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Dendy
Гость
« Ответ #19 : Декабрь 08, 2006, 14:01 »

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

Сразу бросается в глаза отсутствие проверки на пересечение текста и event->rect(). Проверка происходит где-то извне: rowVis(), colVis(). Естественно, что ети проверки вьІберут лишние фрагментьІ, которьІх сейча не видно. Как следствие - лишние вьІзовьІ drawText(). Тормоза из-за накладньІх расходов.
Записан
Tonal
Гость
« Ответ #20 : Декабрь 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. И возвращать именно его.
Тогда, если одновременно изменяется относительно небольшое количество данных, должен получится существенный выигрыш.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #21 : Декабрь 09, 2006, 00:04 »

Рамки - это как раз правильно (вокруг каждой ячейки рисуется черная рамка).

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

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

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

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

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

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Tonal
Гость
« Ответ #22 : Декабрь 09, 2006, 11:33 »

Можно ещё схему кеширования придумать, например, если много значений совпадает, то кешируем не по ячейкам, а по значениям.
Строим QMap<QString, QPixmap>.
Если такой способ не канает, можно построить мап по всем символам, которые могут встречатся в значени, и собираем из них картинку - может получиться быстрее, хотя , думаю это то автоматом делается...

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

Иначе, даже если скорости ты добьешся, смысла в этом не будет. ;-)
Записан
Dendy
Гость
« Ответ #23 : Декабрь 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 с большой страницей.
Записан
Tonal
Гость
« Ответ #24 : Декабрь 09, 2006, 16:14 »

Я так понял, что у Racheengel данные изменяются каждые 50 - 100мсек.
Причём он утверждает, что они ВСЕ изменяются.
И он делает repaint всей таблице.
Не совсем ясно, общее количество строк и столвцов на экране, но тут можно очень быстро до тормозов доехать.

Я бы лучше подумал, как изменить отображение, т.к. с описанной таблицей работать  почти не возможно...
Если это конечно на какой-то двумерный джек-пот, или цветомузыка.
Но тогда не ясно, зачем строки - можно цветами обойтись. ;-)
Записан
Dendy
Гость
« Ответ #25 : Декабрь 09, 2006, 16:25 »

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

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

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #26 : Декабрь 10, 2006, 20:57 »

Приложение - таблица для отображения биржевой активности.
Скоростьб обновления не устраивает клиента Грустный
Да и при скроле мышью притормаживает, неприятно.

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

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Dendy
Гость
« Ответ #27 : Декабрь 10, 2006, 21:27 »

Если вьІложишь проект, которьІй возможно собрать и протестить самому - будеть идеально. А про viewport == event->rect() так ето просто частньІй случай. Правильно нужно делать как в теории, теория описана в документации.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #28 : Декабрь 11, 2006, 00:18 »

Могу выложить, куда?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
cancroid
Гость
« Ответ #29 : Декабрь 11, 2006, 14:51 »

Цитата: "Racheengel"
Могу выложить, куда?


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


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