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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Временно блокировать рисование объекта  (Прочитано 10346 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Сентябрь 29, 2010, 19:16 »

Добрый вечер

Извиняюсь за явно неудачное название темы. Есть массив данных, каждый элемент довольно сложная структура. Элементы могут рисоваться во многих окнах и очень по-всякому. В какой-то момент получена команда: (пере) создать один из элементов. Это модальный процесс, но все же окна обновлять надо (напр переключились на др. задачу и обратно). Проблема в том что когда идет процесс создания элемента - рисовать его нельзя, нужные данные отсутствуют, вылетаем.

Понятно что решение не одно. Напр. можно завести для элемента флажок locked и если взведен - не рисуем. Но мне это не очень нравится - придется вставлять эту проверку во все (разнообразные) рисования. Какие есть еще возможности?

Спасибо
Записан
Akon
Гость
« Ответ #1 : Сентябрь 29, 2010, 22:06 »

Не совсем понятна проблема.

Элемент данных изменился/создался/удалился - бросается сигнал, в окнах слоты и далее обновление окон.

Что за специфика?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Сентябрь 29, 2010, 23:16 »

Не совсем понятна проблема.

Элемент данных изменился/создался/удалился - бросается сигнал, в окнах слоты и далее обновление окон.

Что за специфика?
Изменение может занимать несколько минут. В это время пользователю запрещается что-то нажимать (кроме кнопки Cancel), но отрисовывать окна все равно надо
Записан
Akon
Гость
« Ответ #3 : Сентябрь 30, 2010, 10:38 »

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

Можно в объекте данных генерировать события:

Код:
Q_SIGNALS:
void updating();   // перед обновлением
void duringUpdate(); // в процессе обновления несколько раз
void updated(); // после обновления

Соответственно:
updating() - рисуешь что-то типа "Ждите..." (как правило, напрямую через QWidget::repaint());
duringUpdate() - если все в главном потоке, то обрабатываешь сообщения (QCoreApplication::ProcessEvents()), чтобы была возможность нажать на кнопку Cancel; также можешь выводить процент выполнения;
updated() - вожделенная отрисовка.
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #4 : Сентябрь 30, 2010, 13:07 »

Можно менять долго копию объекта, а в конце по ОК быстро вставить в основную структуру...

Наверное, правильного решения здесь нет, все зависит от трудозатрат/существующей реализации/ и пр факторов
Записан

Гугль в помощь
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Сентябрь 30, 2010, 13:24 »

Можно в объекте данных генерировать события:

Код:
Q_SIGNALS:
void updating();   // перед обновлением
void duringUpdate(); // в процессе обновления несколько раз
void updated(); // после обновления
В данном случае объект пассивен, окно знает контейнер объектов которые надо нарисовать

Можно менять долго копию объекта, а в конце по ОК быстро вставить в основную структуру...
Это выглядит хорошо, но обойтись оператором = не удается. Объект зарегистрирован, его удаление вызывает запись undo на диск и.т.п.  А вот "заблокировать" объект достаточно легко.

Код
C++ (Qt)
DisplayData * MyObject::GetDisplayData( void );
 

Все вызывающие проверяют возвращаемое значение на ноль, рисование безопасно. Но ведь "создающие" тоже пользуются тем же GetDisplayData, по сути они его и заряжают.
Записан
Akon
Гость
« Ответ #6 : Сентябрь 30, 2010, 14:11 »

Обычно, если объектов много (их неэффективно делать QObject'ами), то активен QObject контейнер. В сигналах контейнера будут передаваться объекты. Без сигналов все равно не обойтись.

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Сентябрь 30, 2010, 15:06 »

Обычно, если объектов много (их неэффективно делать QObject'ами), то активен QObject контейнер. В сигналах контейнера будут передаваться объекты. Без сигналов все равно не обойтись.
Не очень понятно кто кому сигналит  Улыбающийся Если все сводится к ф-ции-члену типа CanBeDrawn (по существу флажок предложенный в #1), то меня это не устраивает, если нужно расскажу почему. Если имеется ввиду что-то другое - поясните.
Записан
Akon
Гость
« Ответ #8 : Сентябрь 30, 2010, 20:28 »

Окна отображают данные с контейнера. В контейнере что-то изменяется/добавляется/удаляется. Как окна узнают об этом? Посредством подписки на сигналы с контейнера. Короче паттерн "Наблюдатель". Я это имел ввиду.

В твоем случае, поскольку процесс обновления длительный и с Cancel'ом, вместо одного сигнала я предложил три.

Под контейнером я понимаю объект логики, а не что-нибудь примитивное вроде QList.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Сентябрь 30, 2010, 20:43 »

Окна отображают данные с контейнера. В контейнере что-то изменяется/добавляется/удаляется. Как окна узнают об этом? Посредством подписки на сигналы с контейнера. Короче паттерн "Наблюдатель". Я это имел ввиду.

В твоем случае, поскольку процесс обновления длительный и с Cancel'ом, вместо одного сигнала я предложил три.
Ну эффект 3-х тот же. Окно не может разбираться с каждым объектом индивидуально - нет смысла т.к. объекты могут перекрывать друг друга произвольным образом. Поэтому реально окно рисует все объекты контейнера. И если какой-то объект не готов - рухнет
Записан
Akon
Гость
« Ответ #10 : Сентябрь 30, 2010, 21:08 »

Объекты обновляются в своем потоке или GUI'шном?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Сентябрь 30, 2010, 21:25 »

Объекты обновляются в своем потоке или GUI'шном?
Здесь все просто в главной нитке - но это не делает жизнь легче  Улыбающийся
Записан
Alex_cs_gsp
Гость
« Ответ #12 : Сентябрь 30, 2010, 21:40 »

Но мне это не очень нравится - придется вставлять эту проверку во все (разнообразные) рисования. Какие есть еще возможности?
Спасибо

А если эти все разнообразные рисования вывести через наследование? - тогда пусть флажок в базовом классе проверяется.
Например
Код:
class CBase
{
    public:
         virtual void SomePrint() = 0;

    private:
         void _DoPrint() {if(flag)this->SomePrint();}
};


class CDerive : public CBase
{
    public:
    void SomePrint();
};

А когда нужна перерисовка, вызывать метод _DoPrint() ? Или как-то так.
« Последнее редактирование: Сентябрь 30, 2010, 21:42 от Alex_cs_gsp » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Сентябрь 30, 2010, 21:52 »

А если эти все разнообразные рисования вывести через наследование? - тогда пусть флажок в базовом классе проверяется.
Завести флажок (метод, сигнал) - не вопрос. Проблема в том что проверять его придется из очень многих мест. Во-первых, рисующих окон не одно, и даже не 10 (хотя одновременно открытых обычно немного). Во-вторых, объект может участвовать в рисовании неявно. Пример: должно рисоваться "нечто среднее" между 2-мя объектами (морф). Тогда сами объекты не рисуются, но чтобы получить это среднее - надо иметь DisplayData каждого, т.е. проблема та же. 
Записан
Alex_cs_gsp
Гость
« Ответ #14 : Сентябрь 30, 2010, 21:58 »

А через фильтр сообщений не получится?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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