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

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

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

Сообщений: 11445


Просмотр профиля
« : Сентябрь 18, 2020, 13:17 »

Добрый день

Хочу такой ф-ционал (псевдокод)
Код
C++ (Qt)
while (IsMouseDown()) {
 QPoint pt = GetMousePosition();
 if (pt != oldPt)
  DragSomething(pt);
 oldPt = pt;
}
 
Ну конечно цивильно, а не жрать проц в IsMouseDown. Какие есть решения?

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

Сообщений: 2679


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


Просмотр профиля
« Ответ #1 : Сентябрь 18, 2020, 17:54 »

например добавить

qApp->processEvents();
QThread::msleep(100);
Записан

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 не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Сентябрь 18, 2020, 20:56 »

например добавить

qApp->processEvents();
QThread::msleep(100);
"Please be more concrete". Что должно быть в IsMouseDown?
Записан
RedDog
Частый гость
***
Offline Offline

Сообщений: 221


Просмотр профиля
« Ответ #3 : Сентябрь 18, 2020, 20:59 »

локальный  QEventLoop нельзя подписать на moseDown ?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Сентябрь 18, 2020, 22:44 »

локальный  QEventLoop нельзя подписать на moseDown ?
"Прошу исполнить"
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


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


Просмотр профиля
« Ответ #5 : Сентябрь 20, 2020, 01:11 »

но вообще на mouseMove надо реагировать.
передвинулась мышь? проверили, зажата ли кнопка. если да - что-то драгаем.
Записан

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 не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Сентябрь 20, 2020, 10:37 »

но вообще на mouseMove надо реагировать.
передвинулась мышь? проверили, зажата ли кнопка. если да - что-то драгаем.
Это размазывает код между событиями, что далеко не всегда удобно, особенно при обильных и/или сложных драгах. Гораздо приятнее написать весь драг в одном месте, от начала до конца. Разве это запрещено? Нарушает какие-то прынцыпы? Удивляет неуверенность ответов, ведь гуй - Ваше родное, я же не о матрицах спрашиваю Улыбающийся Почему не так (псевдокод)

Код
C++ (Qt)
extern bool isDragging = false;
 
bool IsMouseStillDown( void )
{
  if (!isDragging) {
   qApp->installEventFilter(&myFilter);
   isDragging = true;
  }
 
  qApp->processEvents(QEventLoop::WaitForMoreEvents);
 
  if (!isDragging)
   qApp->removeEventFilter(&myFilter);
 
 return isDragging;
}
 
Ну и в myFilter жрать события мыша пока не придет нужное MouseRelease, тогда сбросить флажок isDragging.

Хорошо ли это, какие здесь проблемы?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #7 : Сентябрь 20, 2020, 11:05 »

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

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Сентябрь 20, 2020, 11:37 »

Igors придумал корутины
Ну мыслящий человек обязан что-то придумывать Улыбающийся Но корутины-то здесь причем? Открыл гугл
Цитировать
Корутины — это новый способ написания асинхронного, неблокирующего кода.
В чем его новизна - хз, просветите. Но никакой асинхронности здесь нет.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


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


Просмотр профиля
« Ответ #9 : Сентябрь 21, 2020, 09:46 »

Хорошо ли это, какие здесь проблемы?

Хорошего ничего не вижу, кроме недостатков.
Пытаясь уйти от проблемы "размазывания кода", Вы создаёте несколько новых проблем.
1. Появляется второй ивент-луп в том же гуй-потоке.
2. Создается дополнительный фильтр событий, которому всё равно нужен отдельный обработчик.
3. Откуда будет зваться IsMouseStillDown() ?
4. Опять же, нужен обработчик логики драга. Что делать, если начали драг с зажатым Ctrl? Или если поведение логики дропа меняется, в зависимости от того, где отпустили мыш?

В общем без дополнительных методов не обойтись, ну а тогда в чём выигрыш данного подхода?

Вообще тема драг-дропа довольно гнилая с точки зрения "прынцыпов", потому что, как правило, приходится в любом случае либо городить огромную state-machine, либо много драг-хендлеров.

Я бы сделал вместо своего ивент лупа базовую обработку типа "нажал (mousePress) - подвинул мыш (mouseMove) - отпустил (mouseRelease)". А уже из mouseMove() вызывать что то типа void onDragging(CMyObject* draggedObject). А уже из данного метода, в зависимости от того, кем является draggedObject (и есть ли он вообще - вдруг юзер решил рабочее поле драгать? например, для выделения или скролла) - вызывать соответсвующие обработчики драгов.

"я так делал, так работает" (с) я
« Последнее редактирование: Сентябрь 21, 2020, 10:04 от Racheengel » Записан

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 не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Хорошего ничего не вижу, кроме недостатков.

Пытаясь уйти от проблемы "размазывания кода", Вы создаёте несколько новых проблем.
1. Появляется второй ивент-луп в том же гуй-потоке.
2. Создается дополнительный фильтр событий, которому всё равно нужен отдельный обработчик.
3. Откуда будет зваться IsMouseStillDown() ?
4. Опять же, нужен обработчик логики драга. Что делать, если начали драг с зажатым Ctrl? Или если поведение логики дропа меняется, в зависимости от того, где отпустили мыш?

В общем без дополнительных методов не обойтись, ну а тогда в чём выигрыш данного подхода?
Давайте "говорить об одном и том же" (первый закон логики). Я предложил обсудить проблемы реализации IsMouseStillDown. Да, они непросты, не исключено что именно поэтому желаемый ф-ционал недостижим. Вы же утверждаете что данный ф-ционал вообще неполноценен и не дает выгод. Это не так, выгоды как раз очевидны. Во-первых, IsMouseStillDown пишется один раз на все случаи жизни - уже хорошо. Зовется она при всяком драге, обычно из обработчика MousePressed, тут возможно не понял что Вы имели ввиду. И уж тем более не понял последнего пункта

4. Опять же, нужен обработчик логики драга. Что делать, если начали драг с зажатым Ctrl? Или если поведение логики дропа меняется, в зависимости от того, где отпустили мыш?
Тут как раз все прекрасно. Нужны доп клавиши - просто снял их перед циклом while или или внутри него или передал аргументом от исходного MousePressed. Изменился target под мышей -ну зафиксировали это в локальной объявленной до цикла while (напоминает выгоды лямбды). Наоборот, в событийной схеме все это пусть несложно, но очень хлопотливо.
 
Я совсем не предлагал реализовывать какую-то логику драга в IsMouseStillDown, она просто возвращает false (= мыш отпущен) или true (= мыш зажат, но что-то случилось) - и все 

"я так делал, так работает" (с) я
У меня тоже многое (или почти все) работает, но далеко не всем я могу гордиться  Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Да, и забыл пожалуй главное  Улыбающийся "Модальность". Напр драгается нечто по MouseMoved - но это никак не запрещает др событий, глупый юзвеоь может напр закрыть окно и.т.п. Женщины в таких случаях советуют "А зачем Вы это нажимали? Не нужно было этого делать"  Улыбающийся
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


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


Просмотр профиля
« Ответ #12 : Сентябрь 21, 2020, 12:46 »

Да, и забыл пожалуй главное  Улыбающийся "Модальность". Напр драгается нечто по MouseMoved - но это никак не запрещает др событий, глупый юзвеоь может напр закрыть окно и.т.п. Женщины в таких случаях советуют "А зачем Вы это нажимали? Не нужно было этого делать"  Улыбающийся

Ну глупый юзверь будет драгом занят, во время драга мыш зажат, он физически на закрытие окна кликнуть не сможет.
Записан

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 не волк, в лес не уйдёт
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



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

Зато на Alt-F4 нажать сможет легко. Улыбающийся
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


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


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

Получается следующая петрушка:

если делать на "стандартных" мышесобытиях, то выглядеть будет примерно так:

Main Thread (GUI)
"Main Event Loop":

Код:
::onMousePressed(MouseEvent *e):
   m_clickPosition = e->pos();
   m_objectDragged = findObjectAt(m_clickPosition);
   m_isDrag = true;

::onMouseReleased(MouseEvent *e):
   hangleRelease(e->pos(), m_objectDragged);
   m_isDrag = false;

::onMouseMoved(MouseEvent *e):
   if (m_isDrag)
     handleDrag(e->pos(), m_objectDragged)

"Свои имплементации":
hangleDrag() - тут тянем объект (меняем координаты whatever)
hangleRelease() - тут дропнули объект



А если на "локальном эвентлупе":

Main Thread (GUI)
"Main Event Loop":

Код:
::onMousePressed(MouseEvent *e)
{
   m_clickPosition = e->pos();
   m_objectDragged = findObjectAt(m_clickPosition);
   m_isDrag = true;

  m_oldPosition = e->pos();

  installFilter(this);

   while (m_isDrag)
   {
      if (m_oldPosition != m_lastEvent ->pos())
      {
         m_oldPosition = m_lastEvent ->pos();
         hangleDrag(m_lastEvent , m_oldPosition);
      }

      qApp->processEvents();
      msleep(...);
   }

  uninstallFilter(this);

  hangleRelease(m_lastEvent ->pos(), m_objectDragged);
}


::onMouseReleased(MouseEvent *e)
{
  m_lastEvent = e;
  m_isDrag = false;
}


::onMouseMoved(MouseEvent *e)
{
   if (m_isDrag)
     m_lastEvent = e;
}

То есть стало больше кода, появился фильтр эвентов, промежуточные переменные, и всё равно надо имплементировать hangleDrag() и hangleRelease()...
Не понятно, где мы выигрываем Непонимающий
Записан

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 не волк, в лес не уйдёт
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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