Название: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Октября 02, 2009, 13:00 Мы можем любому виджету изменить текст, картинку, что угодно с помощью различных методов, как то setText(), setPixmap() и.т.д.
При этом если программа достаточно легкая, то мы видим перерисовку сразу. В более сложной программе, где количество событий велико, в том числе существуют пользовательские события, установка методом set*** не всегда приводит к перерисовке сразу? Это результат того, что событие отрисовки для данного виджета встало в очередь событий? Метод update() с последующий QApplication::processEvents() вызовет мгновенную отработку отрисовки? Правильно? И еще вопрос. Если в собственном обработчике событий, возникает другое событие, в том числе и по перерисовке элементов интерфейса, то все последующие события встанут в очередь событий? processEvent сможет прервать его для обновления перерисовки? Или я не правильно понимаю логику Qt? Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Igors от Октября 02, 2009, 13:23 Ну здесь легко "залезть в дебри" :) В общих чертах: update() мгновенной перерисовки не обещает, если есть такая необходимость - нужно использовать repaint()
Запрос на перерисовку помещается в системную очередь событий и его приоритет ниже других событий, т.е. пришедшие позже события могут выполняться до перерисовки. OS может объединять/сливать несколько перерисовок в одну. С обновлением экрана (видеопамяти) тоже не все просто, некоторые OS держат окна "double-buffered" и имеют еще один уровень "выталкивания" в видео. Например, если Вы нарисуете синий квадрат, а затем поверх него красный, на одних OS это будет мигать а на других нет. В общем это очень большой огород и вникать во все нюансы может и не стоит. Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Октября 02, 2009, 13:53 Хорошо, как правильно обновлять тогда? Что лучше использовать?
Правильно вызывать processEvents? Чтобы протолкнуть вызов события перерисовки? Или repaint() выполнит это сам? Как вариант ведь можно использовать вызов update() по таймеру. Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Igors от Октября 02, 2009, 15:15 Хорошо, как правильно обновлять тогда? Что лучше использовать? 1) update() по таймеру ничего не дает, т.к. update только засылает запрос на перерисовку в очередьПравильно вызывать processEvents? Чтобы протолкнуть вызов события перерисовки? Или repaint() выполнит это сам? Как вариант ведь можно использовать вызов update() по таймеру. 2) processEvents здесь ничего не ускорит 3) repaint перерисует (сейчас же) и удалит все запросы перерисовки из очереди, другие события он не тронет. Но вызывать repaint() по таймеру как минимум ненадежно - приоритет события по таймеру тоже низкий. Итого: надо вставить repaint() в те места, где идут тяжелые расчеты и перерисовка не успевает. Допустим один раз на 100 вычислений в цикле (или на 1000, подобрать). Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Октября 05, 2009, 06:55 А использование setUpdatesEnabled() поочередно ведь тоже можно испрользовать, насколько я понимаю?
{ ... setUpdatesEnabled(true); repaint(); setUpdatesEnabled(false); ... } Чтобы не было ненужных перерисовок, а все перерисовки при сложных вычислениях шли только по repaint'у. Так верно - или это будет излишним? Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Igors от Октября 05, 2009, 08:57 А использование setUpdatesEnabled() поочередно ведь тоже можно испрользовать, насколько я понимаю? 100% верно и чище{ ... setUpdatesEnabled(true); repaint(); setUpdatesEnabled(false); ... } Чтобы не было ненужных перерисовок, а все перерисовки при сложных вычислениях шли только по repaint'у. Так верно - или это будет излишним? Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Октября 05, 2009, 12:55 Вот вопрос. А вызов repaint из обработчика только paintEvent вызывает рекурсию? Или из любых обработчиков?
Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Igors от Октября 05, 2009, 13:24 Вот вопрос. А вызов repaint из обработчика только paintEvent вызывает рекурсию? Или из любых обработчиков? "Только". Если в paintEvent вставить repaint, то он позовет тот же paintEvent - бесконечный рекурс (пока хватит стека). В др. обработчиках этого не произойдет. Также предполагается что метод paintEvent не порождает никаких событий, это плохо в любом случае.Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Октября 05, 2009, 13:42 Вот вопрос. А вызов repaint из обработчика только paintEvent вызывает рекурсию? Или из любых обработчиков? "Только". Если в paintEvent вставить repaint, то он позовет тот же paintEvent - бесконечный рекурс (пока хватит стека). В др. обработчиках этого не произойдет. Также предполагается что метод paintEvent не порождает никаких событий, это плохо в любом случае.То есть все равно приходим к одному. Лучше исользовать update(). И проталкивать событие через processEvents? Получается так? Если хотим все-таки увидеть перерисованную область =) И еще, вызов update не вызывает рекурсию при вызове даже из eventPaint, Верно? потому как все равно встанет в очередь, и уже потом соединится с какими-то другими перерисовками и будет обработано в порядке очереди. Тое есть вызов update() безопасен из любого места программы? Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Igors от Октября 05, 2009, 14:39 То есть все равно приходим к одному. Лучше исользовать update(). И проталкивать событие через processEvents? Вот типичный пример когда нужен processEvents (вторичный цикл событий)Получается так? Если хотим все-таки увидеть перерисованную область =) И еще, вызов update не вызывает рекурсию при вызове даже из eventPaint, Верно? потому как все равно встанет в очередь, и уже потом соединится с какими-то другими перерисовками и будет обработано в порядке очереди. Тое есть вызов update() безопасен из любого места программы? Программа что-то интенсивно считает. События накапливаются в очереди, но поскольку программа занята расчетом, никто их оттуда не извлекает и не обрабатывает, все "заморожено" для пользователя. Таймер здесь не поможет - это тоже событие. В этом случае показывают окно с бегунком (индикатором) и кнопкой "cancel". В вычислениях функция которая периодически продвигает бегунок, вызывает processEvents и затем проверяет была ли нажата "cancel". Это гарантирует что индикатор будет перерисован и "cancel" будет пойман. Теперь смотрите сами это Ваш случай или нет. Если у Вас глухие расчеты - то да. Если же Вы что-то делаете с UI - то нет. Во-первых, processEvents может и не убрать задержку с рисованием, например если интенсивно создаются другие события которые опережают рисование. А главное - processEvents разрешит все др. события и будут вызваны их обработчики. А это может быть совсем не гуд пока Вы не закончили свои дела с UI. Поэтому если управление нужно держать - надо использовать repaint, а не processEvents Ну вроде все (а то я расписАлся :)) Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Октября 05, 2009, 14:46 У нас не глухие расчеты, но выполнение методов set*** много. Много разных других потоков и есть обработчики событий, но не eventPaint. И зачастую бывает, что уже произошла установка set***, а отображения на экране нет. А нужно вовремя это делать.
Вот какой метод выбрать - это вопрос. В принципе, можно и repaint(). Но большое количество вызовов - вызовет мерцание, насколько я понимаю. А update тогда - толково вызывать только при вызове processEvents. Иначе неясно, когда же все обновится. Наверно, стоит отдать предпочтение update(). Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Октября 07, 2009, 08:51 Созрел еще вопрос.
У меня происходит обработка какого-то пользовательского события в event(). Обрабатывая событие у меня изменяется состояние пользовательского интерфейса. Но мне нужно его вовремя обновить. Я, конечно, могу сделать запрос update(). Но он встанет в очередь. Получается вызов QApplication::processEvents() отсюда делать нельзя? Потому как это вызов обработки событий из самого обработчика? НАсколько это корректно? Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Igors от Октября 07, 2009, 12:01 Созрел еще вопрос. Если используете processEvents - Вы должны быть уверены что все обработчики (которые processEvents позовет) не будут конфликтовать с кодом/обработчиком из которого processEvents вызван. Это удается обеспечить далеко не всегда. Если (как я понял) у Вас проблема с отрисовкой то решайте через repaint, стандартный прием - прицепить к нему clock. ПсевдокодУ меня происходит обработка какого-то пользовательского события в event(). Обрабатывая событие у меня изменяется состояние пользовательского интерфейса. Но мне нужно его вовремя обновить. Я, конечно, могу сделать запрос update(). Но он встанет в очередь. Получается вызов QApplication::processEvents() отсюда делать нельзя? Потому как это вызов обработки событий из самого обработчика? НАсколько это корректно? Код: void Repaint2( QWidget * w ) Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Декабря 10, 2009, 15:36 Еще вопрос.
Есть обработчик пользовательских событий в главном окне: Код: MainWindow::customEvent(QEvent *event) Есть мой виджет со своим обрабочиком событий перерисовки: Код: QMyWidget::paintEvent() В принципе нужно что-то изменять на интерфейсе. Есть мой графический элемент QMyWidget *myWidget. Можем ли мы для него вызвать в обработчике событий главного окна метод update()? В принципе, ничего не мешает встать новому событию в очередь событий и обработаться позже. Правильно? Никаких логических ошибок нет? Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Igors от Декабря 10, 2009, 16:13 Правильно? Никаких логических ошибок нет? Я лично не вижу:) Многие обработчики зовут update() и это нормально, нельзя только делать это из paintEventНазвание: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Декабря 14, 2009, 07:54 а где-то можно прочитать, что такой вызов update из обработчика событий разрешен? Именно из официальных источников... Что-то в ассистанте не нахожу... ???
Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: spectre71 от Декабря 14, 2009, 09:28 а где-то можно прочитать, что такой вызов update из обработчика событий разрешен? Именно из официальных источников... Что-то в ассистанте не нахожу... ??? Читай в QT Assistant. void QWidget::update () Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Danila_Bagrofff от Декабря 15, 2009, 09:52 народ, а можно получить вашу оценку одной гениальной идеи обновления:
Мы попадаем в пользовательский обработчик событий customEvent(), где вместо обновления виджета добавляем его в список для последующего обновления в таймере. Получаем список объектов, которые надо обновлять. Запускается таймер с определенной частотой, который для каждого объекта из списка вызывает update() Затем вызывается processEvents, который проталкивает очередь событий и выполняет отрисовку. И при этом хотят, чтобы быстро произошло обновление, в соотвествии с текущим состоянием. Я не понимаю, как можно такое реализовать: Cам таймер обрабатывается через eventTimer(). Вызывая события... В результате processEvents() будет попадание в обработчик и снова может быть вызван customEvent() с последующей установкой виджетов на обновления. Время таймера, по-моему, никак нельзя согласовать... К тому же оно само обрабатывается по событию... НАсколько будет своеевременность обновления - у меня тоже сомнения... ПС, идея не моя.. свое мнение об этом оставлю в стороне, интересно ваше мнение... Название: Re: Обновление(перерисовка) состояния виджетов. set*** и update(). Вопрос. Qt 4.5.0 Отправлено: Dendy от Декабря 17, 2009, 01:12 Это чревато визуальной задержкой, когда пользователь успеет заметить латентность отклика. При мышиных/клавиатурных действиях такое нежелательно. А вообще - нормальная идея, если нужно склеить несколько обновлений в одно. К примеру, состояние долгой операции (качание файла) совсем не обязательно обновлять каждые 1 мс, достаточно накопить изменения и показать их через 1 с. Например:
Код
|