LINUX.ORG.RU

[Qt] Сжатие нескольких событий одного типа в одно.

 


0

1

В документации Qt есть такая штука:

postEvent() отправляет событие в очередь для последующей координации. В следующий раз основной цикл обработки событий Qt работает, он координирует все отправленные события, с некоторой оптимизацией. Например, если имеется несколько событий изменения размера, они сжимаются в одно. То же самое относится к событиям рисования:

Если я решу создать свой собственный event (унаследую от QEvent), то как мне заставить несколько таких событий в очереди «сжиматься в одно»?

★★★★★

Кому интересно, я хочу создать событие anchorMoveEvent. У меня в приложении есть привязка (как в cad-ах), которая меняет своё место при движении мыши, соответственно активный инструмент на это реагирует. Плюс информация о позиции привязки отображается в статусной строке.

Сейчас это сделано сигналом, но как мне кажется, логичней сделать это событием.

Obey-Kun ★★★★★
() автор топика

>Если я решу создать свой собственный event (унаследую от QEvent), то как мне заставить несколько таких событий в очереди «сжиматься в одно»?

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

Если следующее другое - пускать текущее, а следующее класть в очередь итд.

И, естественно, всё с мелким таймаутом.

anonymous
()

Унаследуй QApplication и переопредели compressEvent().

summatus
()

>В следующий раз основной цикл обработки событий Qt работает, он координирует все отправленные события, с некоторой оптимизацией

Ты неверное перевёл неправильно... там всё проще.

summatus
()
Ответ на: комментарий от Obey-Kun

Смысл в том, что события «сжимаются» сразу в функции postEvent, т.е. до «основного цикла обработки событий» дело не доходит... Доки не читал... =)

summatus
()

Я бы не советовал переопределять compressEvents(): это недокументированная фича, в будущем ее могут убрать/поменять, и тебе все придется переписывать.

Лучше действительно сделайте локальную очередь событий. При добавлении первого события в нее с помощью postEvent() отправляйте кастомное Qtшное событие MyQueueIsNotEmptyEvent. Соответственно при обработке MyQueueIsNotEmptyEvent-а обрабатывайте эту локальную очередь, чтобы на выходе она вновь была пуста.

LORd
()
Ответ на: комментарий от LORd

Я бы не советовал переопределять compressEvents(): это недокументированная фича, в будущем ее могут убрать/поменять, и тебе все придется переписывать.

Спокойно юзаю кучу недокументированых фич типа QLatin1Literal и особых проблем не испытываю, как-бы эти фичи не в приватных классах сидят и поэтому между мажорными версиями Qt они тоже не могут меняться.

Gorthauer ★★★★★
()
Ответ на: комментарий от LORd

>Лучше действительно сделайте локальную очередь событий

Если есть надежда на совместимость с Qt 5, да, конечно так правильней. Только кода будет больше.

summatus
()
Ответ на: комментарий от LORd

> Лучше действительно сделайте локальную очередь событий. При добавлении первого события в нее с помощью postEvent() отправляйте кастомное Qtшное событие MyQueueIsNotEmptyEvent. Соответственно при обработке MyQueueIsNotEmptyEvent-а обрабатывайте эту локальную очередь, чтобы на выходе она вновь была пуста.

Не въехал :(. Можно приблизительный список небходимых к созданию классов и методов, а также принцип использования?

p.s.: в моём случае важна только итоговая позиция привязки.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Можно приблизительный список небходимых к созданию классов и методов, а также принцип использования?

Принцип простой:

1.

struct SMyEvent
{
   ...... // координаты и пр
};

2. в объект, который будет генерировать события, добавляем следующее:

class MyObject : public QObject
{
Q_OBJECT
...
private:
   QList<SMyEvent *> m_myQueue;
   void postMyEvent(SMyEvent * _e);

private slots:
   ....
   void processMyQueue(); // будет вызываться из Qt-шного event-loop-а

signals:
   ....
   void myQueueIsNotEmpty();

};

3. в конструкторе MyObject-а:

MyObject::MyObject(...) ...
{
    ... 
    // QueuedConnection - чтобы processMyQueue() не вызывался
    // сию минуту, а "шедулился" в Qtшном eventloop-е.

    QObject::connect(this, SIGNAL(myQueueIsNotEmpty()),
       this, SLOT(processMyQueue()), Qt::QueuedConnection);
   ...
}

4.

void MyObject::postMyEvent(SMyEvent * _e)
{
    m_myQueue << _e;
    if (m_myQueue.size() == 1) {
        // В принципе сигналы/слоты можно заменить на
        // кастомное событие/postEvent(), суть одна
        emit myQueueIsNotEmpty();
    }
}

5.

void MyObject::processMyQueue()
{
   ....
   собственно тут происходит компрессия итдитп
   ....
}

Ну а как это организовать/инкапсулировать - это уже вопрос к вашим эстетическим предпочтениям :)

LORd
()
Ответ на: комментарий от LORd

Да, ну и нужно гарантировать, что в конце вызова processMyQueue() , что очередь очистится

void MyObject::processMyQueue()
{
   ....
   собственно тут происходит компрессия итдитп
   ....
   Q_ASSERT(m_myQueue.size() == 0 && "queue is not empty");
}

LORd
()
Ответ на: комментарий от LORd

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

Obey-Kun ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.