Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Обработка событий в потоке, QT

414
11 августа 2013 года
CassandraDied
763 / / 24.05.2012
Хай.
Есть DLL, в которой запускаю поток QThread, в котором запускаю цикл QApplication. Так же в потоке создаётся диалог и таймер. Диалог скрывается по таймеру.
У диалога переопределены обработчики событий мыши.
Почему-то обработка сигналов от таймера происходит вовремя, без задержек. А вот сигналы от мыши обрабатываются только в том случае, если вызвать ресайз формы.
То есть, если я кликнул правой кнопкой мыши на диалоге и не изменил его размеров, то форма может скрыться по таймеру так и не обработав событие мышки. Почему так?
Немного кода:

 
Код:
void MThread::run()
{
  MThread::_app = new QApplication(_argc, _argv);
  _main_window = new SongTitle();
  _main_window->SetTitle(QString::fromLocal8Bit("lalala"));
  _main_window->ShowTitle();
  //this->exec();
  MThread::_app->exec();
}

Код:
void SongTitle::mouseReleaseEvent(QMouseEvent *event)
{
  MessageBoxW(0, L"in mouse event",L"",0);
  switch (event->button()){
    case Qt::LeftButton:
      MessageBoxW(0, L"left",L"",0);
      break;
    case Qt::RightButton:
      MessageBoxW(0, L"right",L"",0);
      break;
    default:
      QDialog::mousePressEvent(event);
      break;
    }
}
6.0K
14 августа 2013 года
artyom-tyanutov
107 / / 10.07.2006
Весь GUI обязан быть в главном потоке приложения.
326
16 августа 2013 года
sadovoya
757 / / 19.11.2005
Похоже Qt gui весь должен быть в главном потоке и видимо это не обойти. Реализация событийной системы там своя, не нативная (хотя нативные события встроить можно), логикой виндовых окон там не обойтись. Сильно сомневаюсь, что в дочернем потоке хотя бы api-шный gui можно в Qt-программах использовать (по той-же причине). Хотелось бы, чтобы я заблуждался, может кто опровергнет?
414
16 августа 2013 года
CassandraDied
763 / / 24.05.2012
Эх, sadovoya, и ты туда же...
Ну хорошо. Кто объяснит мне, чем главный поток принципиально отличается от того, что создаётся через QThread?
7
16 августа 2013 года
@pixo $oft
3.4K / / 20.09.2006
Тем, что он главный и его логика жёстко прописана в ядре. Может, из остальных потоков события не так обрабатываются, или ещё что. Вариантов масса, и без копания в исходниках вряд ли можно многое узнать.
414
16 августа 2013 года
CassandraDied
763 / / 24.05.2012
Ну, исходники есть в первом посте. Читайте, говорите.
Так же там есть намёк на главный поток, в контексте которого запускается второстепенный и сам GUI.
К тому же, если бы я накосячил с потоками, мне бы в debug console вывалилась надпись о том, что виджеты можно создавать только в главном потоке, ничего бы не стало работать, а форма отображается.
7
16 августа 2013 года
@pixo $oft
3.4K / / 20.09.2006
Эти исходники — не исходники ядра Qt.
Создаться и отображаться она может, а вот остальная логика может рандомно поехать — например, как в твоём случае. А что отладка показывает?
414
16 августа 2013 года
CassandraDied
763 / / 24.05.2012
Ну, докопаться до ядра диспатчера сообщений оказалось непосильно сложно...Отследить их перемещение тоже не вижу возможности. Но никаких ошибок нет, в debug console ничего не пишется.
Вот что странно: сообщения от таймера обрабатываются как надо, а сообщения от мыши лагают. И пинок для обработки сообщений мыши даёт именно событие перерисовки окна. Я даже представить не могу, какой механизм мог бы работать и с какой логикой.
Возможно, это баг. За троллями такое частенько наблюдается. А работа с потоками в DLL — вообще больная тема.
Раз на SO никто не подсказал ничего, видимо, лучше оставить эту тему и как-то выкручиваться иначе.
326
16 августа 2013 года
sadovoya
757 / / 19.11.2005
Никакой ни баг, в доках об этом пишут. Сообщения, не направленные конкретно к gui-шным элементам, может и нормально обрабатываются, а всякие ресайзы связаны с гуи и могут глючить. Думаю, что подобное с таймером.
414
16 августа 2013 года
CassandraDied
763 / / 24.05.2012
Но ведь сообщение таймера направлено конкретно к форме: сигнал таймера привязан к слоту диалога.
А можно ссылку на доки?
Кстати, я уже пробовал и свою очередь делать, через QEventLoop, но всё равно никаких изменений.
И если это баг, то что я делаю неправильно? Могу залить полностью код проекта.
326
17 августа 2013 года
sadovoya
757 / / 19.11.2005
Это не док, но то, что под рукой нашлось -- C++ GUI Programming with Qt 4 (First Edition) (ISBN 0131872494)
by Jasmin Blanchette & Mark Summerfield. Это книга разрабов Qt, можно ей верить. А в офдоках подтверждение точно находил, возможно даже просто в хелпе Qt.

Сигнал таймера не спецефичен для формы, поэтому благодаря поддержке со стороны кьют и передается нормально. А ресайзы "чисто гуишные" и кьют их в неглавном потоке не обязана обработать верно. Я почти уверен что так происходит.

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

Я все-таки надеюсь, что я не прав в своем мнении о полной невозможности обойти эти запреты. Может хоть в ограниченной области задачь можно безболезненно гуи разбрасывать по потокам? Как-то синхронизовать, обратный вызов или еще какие примудрости? Не может быть, чтобы такой изъян народ не подвиг накопать решение.
414
17 августа 2013 года
CassandraDied
763 / / 24.05.2012
У меня GUI в главном потоке. И даже таймер. И даже Аллах.
Если попытаться создать GUI вне главного потока, программа падает.
Безразлично, в каком именно потоке будет создан GUI, лишь бы в этом потоке был создан экземпляр QApplication, он и будет считать главным.
Алсо, не стал бы доверять книге, где рассматривается QT 4-й версии. С тех пор уже столько воды утекло.
326
17 августа 2013 года
sadovoya
757 / / 19.11.2005
Признаюсь, на 5-ую пока не перешел. Может в их хелпе что есть? Так по опыту 3-я версия сильно от 4-ой отличалась. Возможно 5-ая тоже сильно от 4-ой ушла..
Насчет достаточно гуи и QApplication в один поток и он становится главным -- боюсь тоже боком выйдет когда-то.
414
17 августа 2013 года
CassandraDied
763 / / 24.05.2012
Собственно, это единственный способ реализовать GUI в DLL — создать инстанс QApplication внутри QThread. На всём SO ничего другого я не нашёл, хотя вопрос поднимался не раз.
А про то, что в любом потоке можно создать GUI, лишь бы был инстанс QApplication — это уже либо из документации прочёл, либо из coock book'а, которые собрали комьюнити. Но эта информация тоже не первой свежести, официальный док по потокам ещё не обновился для пятой ветки. А может, там просто и обновлять нечего...
326
17 августа 2013 года
sadovoya
757 / / 19.11.2005
Может не инстанс а ссылку на main-ский qApp? Иначе это сильно смахивает на создание целого процесса, а не потока.. Если что узнаете, отпишитесь плиз.
327
17 августа 2013 года
UserNet2008
748 / / 03.04.2010
Может так
 
Код:
if( QTimer->isActive() )
    {
        "что-то делаем";
    }
else
    {
        "форма может скрыться по таймеру";
    }
414
17 августа 2013 года
CassandraDied
763 / / 24.05.2012
Не, в DllMain создавать qApp не получится, потому что она вызывается в контексте потока приложения, к которому аттачится dll. Если запущу очередь сообщений в потоке приложения, то всё подвиснет, для этого, собственно, и нужен второй поток. Так что инстанс создаётся именно в новом потоке.
Я даже пробовал не запускать цикл qApp, а вместо этого запустить цикл потока, но инстанс всё равно создавал. В коде этот момент закомментирован. И всё работало. Ну, как работало...Так же ситуация, но программа не падала. А когда попытался запустить только поток, не создавая инстанса qApp, то сразу же вылетала ошибка.
Поэкспериментирую ещё, но что-то уже и идей даже нет. Можно попробовать посоздавать все инстансы внутри потока приложения, а цикл обработки событий запустить в новом потоке QThread, Надеюсь, это не подвесит приложение. Но что-то не верится, что такая штука сработает. Там была какая-то особенность для пересылки сигналов между потоками, для них использовался специальный вид подключений.
Отпишусь, если найду решение.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог