Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: sint от Январь 29, 2008, 13:26



Название: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 29, 2008, 13:26
Добрый день.

У меня такая проблема: необходимо отловить событие изменения размеров QWidget с помощью мыши. А трудность в том, что это событие должно отработать только один раз (в момент отпускания пользователем мыши). В виду того, что при этом производятся достаточно тяжелые процессы, переопределение resizeEvent здесь не подходит (отрабатывается многократно, как я понял по таймеру). Решение со временной переменной так же  подошло, т.к. не смог определить какое из resizeEvent является последним.
Уперся в то, что при нажатии или отпускании левой кнопки мыши, к примеру, при находении последнего в нижнем углу окна, (курсор типа Qt::SizeFDiagCursor), не выбрасывается вообще никакого события (включая события  mousePressEvent  & mouseReleaseEvent).
Пытался переопределить event по такому же принципу QApplication или сделать эту форму как дочернюю (mdichild) - все тоже самое.

(Qt 4.3.3 + OpenSuse10.3/win32)

Спасибо.
Дмитрий.

---

Код:
class MyWidget: public QWidget {
 public:
  MyWidget(): QWidget(){ }
 protected:
  virtual bool event ( QEvent * event ){
   qDebug() << "MyWidget::event:" << event->type();
   return QWidget::event (  event );
  }
  virtual void resizeEvent ( QResizeEvent * e ){
   qDebug("MyWidget::resizeEvent");
   QWidget::resizeEvent(e);
  }
};

int main(int argc, char *argv[]){
   QApplication app(argc, argv);
   MyWidget main;
   main.show();
   return app.exec();
 }


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: WW от Январь 29, 2008, 14:03
в ресайзевенте взводишь какой-нить служ. флажок, а в событии отпускания - кн. проверяешь его. если установлен - делаешь свое дело и сбрасываешь флаг.


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 29, 2008, 14:35
Это пробовалось с самого начала и, к сожалению, не подходит. Причина: как я отмечал ранее, я не могу определить какой из resizeEvent будет вызван последним (т.е. интересует именно тот resizeEvent, когда пользователь топустил мышку). При отпускании мыши никакое событие не гененируется. Вообще:-)


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: WW от Январь 29, 2008, 15:58
что, даже mouseReleaseEvent ( QMouseEvent * event )  не генериться???
версия Qt?
Проверил. resizeEvent генериться равно один раз - конце процедуры изменения размера. А на счет mouseReleaseEvent - да, не генериться. Был не прав.


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 29, 2008, 16:25
В том то и проблема. Если бы так было просто, я бы людей не беспокоил:-) Именно если рурсор мыши находится по бордюру окна (когда курсор меняется), эти события (mousePressEvent  & mouseReleaseEvent) не отрабатываются.
(Qt 4.3.3 + OpenSuse10.3/win32)

что, даже mouseReleaseEvent ( QMouseEvent * event )  не генериться???
версия Qt?


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: WW от Январь 29, 2008, 16:26
ответил выше


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: ритт от Январь 29, 2008, 16:34
вв, какая платформа и оконный манагер?


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: WW от Январь 29, 2008, 16:41
под рукой ща винда


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 29, 2008, 17:31
Сейчас у меня тоже винда. Проверил - отрабатывается многократно. Как проверял: запускаю приложение  с консольным выводом из FAR (текст см. ниже). Хватаю мышкой за угол окна и начинаю тягать (изменять размер). Наблюдаю многократный вывод сообщения.
Qt 4.3.1 + WinXP SP2

Файл main.cpp

Код:
#include <QtGui>

class MyWidget: public QWidget {
 public:
  MyWidget(): QWidget(){ }
 protected:
  virtual void resizeEvent ( QResizeEvent * e ){
   qDebug("MyWidget::resizeEvent");
   QWidget::resizeEvent(e);
  }
};

int main(int argc, char *argv[]){
   QApplication app(argc, argv);
   MyWidget main;
   main.show();
   return app.exec();
 }

Файл sample.pro

Код:
TEMPLATE=app
SOURCES=main.cpp
target=./sample
CONFIG += qt warn_on debug console
DESTDIR=./

что, даже mouseReleaseEvent ( QMouseEvent * event )  не генериться???
версия Qt?
Проверил. resizeEvent генериться равно один раз - конце процедуры изменения размера. А на счет mouseReleaseEvent - да, не генериться. Был не прав.


*************************
Пользуйся тегами "Код" для оформления примеров кода! Я же писал уже про это в личку


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: WW от Январь 29, 2008, 18:41
Еще раз проверил. Qt 4.3.2, Win, MSVC2k3. Резайзэвент срабатывает один раз. Проверить под 4.3.3. нет возможности.


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: ритт от Январь 29, 2008, 19:20
вв, проверял этот же код? куда делал вывод дэбага?
у меня аналогичный код прилично спамит мессагами. одно "но" - в венде при изменении размеров окна (драгом) и перетаскивании окна блокируется большинство событий...подозреваю, что ты этим и обманулся

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


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 29, 2008, 20:24
Спасибо большое. Я так пробовал - делал таймер на треть секунды неактивности мыши. Напоролся на другую проблему, которая заставила мне похоронить эту идею:
Все, что касается интерактивной работы - вроде бы этот подход работал нормально, но когда и имеются несколько окон и ПРОГРАММНО их надо перерисовать (я использую SpiderMontkey JavaScript для управления приложением) в короткий срок, то начинаются непонятки с этими таймерами  - несоблюдается последовательность. А бороться с потоками из за такой казалось бы по-началу мелочи морально не был готов. Это раз. А второе и самое главное - при программном управлении и перерисовки, допустим, десятка окон в цикле при решении проблемы "разруливания" их будут заметные тормоза.
Здесь самое обидное то, что не получается отличить программное изменение размеров от изменения посредством мыши (события мыши то не отрабатываются) :-(

А медленное у меня -  рисование карты во временный битмап. От этого и хотел избавиться.

Спасибо за помощь. Будем думать.

Насчет тегов - прошу прощения:-)

вв, проверял этот же код? куда делал вывод дэбага?
у меня аналогичный код прилично спамит мессагами. одно "но" - в венде при изменении размеров окна (драгом) и перетаскивании окна блокируется большинство событий...подозреваю, что ты этим и обманулся

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


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: ритт от Январь 29, 2008, 20:42
отличить программное событие от юзверьского можно - читай доки по ивентам (спонтанус)
но настоящим решением было бы, конечно, избавление от тормозов отрисовки...
заюзай нити, посмотри QMapControl - решение обязано быть!

зы. было бы интересно взглянуть на твой проект


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 29, 2008, 20:58
Ой спасибо, добрый человек, за spontaneous. Выручил. Теперь можно таймеры обратно прикручивать.

Насчет проекта - не могу, извини. Слово дал.

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

зы. было бы интересно взглянуть на твой проект


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 30, 2008, 00:41
Для простого окна решение с spontaneous прокатило, а вот для mdichild нет.
Как вариант меня пока устроил:
Код:
TRWidget*w = new TRWidget(this);
QMdiSubWindow *s = mdiArea->addSubWindow(w, Qt::SubWindow);
s->setOption(QMdiSubWindow::RubberBandResize);

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

зы. было бы интересно взглянуть на твой проект


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: Tonal от Январь 30, 2008, 08:15
Кстати, в WinApi есть оконные события: WM_ENTERSIZEMOVE и WM_EXITSIZEMOVE - я их использовал в такой же ситуации.
Неужели в Qt нет аналога? Может на официальном форуме поспрошать?


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 30, 2008, 10:36
В свое время под Delphi было тоже что то типа resize и resizing (могу ошибиться).
А в qt переопределил event у QWidget, потягал окно и проанализировал по хелпу все, что выдало на консоль. Ничего нужного. Так что вывод неутешителен.

Код:
virtual bool event ( QEvent * event ){
   qDebug() << "MyWidget::event:" << event->type();
   return QWidget::event (  event );
  }


Кстати, в WinApi есть оконные события: WM_ENTERSIZEMOVE и WM_EXITSIZEMOVE - я их использовал в такой же ситуации.
Неужели в Qt нет аналога? Может на официальном форуме поспрошать?


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: Alex03 от Январь 30, 2008, 16:20
ИМХО Отдельный тред создающий нужное изображение - не так уж и страшно.


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Январь 30, 2008, 17:14
Если, допустим, у меня несколько mdichild окон и я даю команду выровнить каскадом.... а при отрисовке используются общие ресурсы... со всеми вытекающими (изменение порядка меньшее из зол). Не думаю, что это тот случай, когда необходима многопоточность :-) Хотя могу ошибиться.
ИМХО Отдельный тред создающий нужное изображение - не так уж и страшно.


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: Germiona от Апрель 09, 2008, 15:50
А не могли бы вы конкретно привести пример использования функции bool spontaneous()


Название: Re: Как поймать событие окончания изменения размеров окна?
Отправлено: sint от Апрель 09, 2008, 21:47
А не могли бы вы конкретно привести пример использования функции bool spontaneous()

Да у меня с этим не получилось. Или я не понял чего. Могу в рамках демонстрации то, что осталось в тестовом проекте.

Код:

class MyWidget: public QWidget {
public:
 MyWidget(): QWidget(){ }
protected:
 /*virtual bool event ( QEvent * event ){
//qDebug() << "MyWidget::event:" << event->type();
 return QWidget::event (  event );
}*/
 virtual void resizeEvent ( QResizeEvent * e ){
  if (e->spontaneous())
   qDebug("mouse");
  else // программно
   qDebug("program");
  QWidget::resizeEvent(e);
 }
 virtual void keyPressEvent(QKeyEvent* e){
  QWidget::keyPressEvent(e);
  if (e->key() == Qt::Key_F4) {
   QSize s = size();
   resize(s.width() +5, s.height() + 5);
  }
 }
};

int main(int argc, char *argv[]){
  QApplication1 app(argc, argv);
  MyWidget wg;
  wg.setGeometry(200, 200, 800, 600);
  wg.show();
  return app.exec();
}