LINUX.ORG.RU

Как отловить момент старта exec() в QDialog?

 ,


0

1

Сделал диалог, унаследованный от QDialog.

Диалог показывает большой набор иконок (несколько разделов по ~1500 иконок). Иконки из одного раздела надо считать с диска, и это занимает около 5 секунд. Поэтому в диалоге предусмотрена процентная линейка, которая показывает процесс загрузки иконок в разделе. И она работает, когда пользователь выбирает тот или иной раздел иконок.

Но возникает проблема с первой отрисовкой диалога. В момент, когда диалог появляется на экране, необходимо загрузить иконки из первого раздела.

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

Вопрос: Как отловить момент старта exec() в QDialog?


PS:

Если запускать загрузку иконок (например сделать метод preloadIcon()) до выполнения exec(), то все работает. За исключением того, что весь интерфейс замирает на 5 секунд, и непонятно что происходит.

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

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


PS2:

Переопределение exec() тоже не помогает. Если сделать так:

int myDialog::exec()
{
  preloadIcon();
  QDialog::exec();
}

То загрузки не будет видно, потому что основной цикл еще не запущен.

А если сделать так:
int myDialog::exec()
{
  QDialog::exec();
  preloadIcon();
}

То до preloadIcon() дело не дойдет, ибо будет ожидание завершения QDialog::exec().

★★★★★

Можно костылем:

dlg->show();
qApp->processEvents();
dlg->preloadIcons();

Можно сделать так:

dlg->show();
QMetaObject::invokeMethod( dlg, "preloadIcons", Qt::QueuedConnection );

Это то что я придумал навскидку, без заглядывания в документацию, а так, можно еще и showEvent переопределить, например.

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

Так и без потока нормально работает. Вопрос только в первом запуске.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от grondek

Я вот думаю с QDialog на QWidget переделать.

Пока не понял, есть ли подводные камни.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от grondek

Можно костылем: qApp->processEvents();

Не сработал. Толку нет, ведь обновления идут в preloadIcons().


Можно сделать так: QMetaObject::invokeMethod( dlg, «preloadIcons», Qt::QueuedConnection );

А тут непонятно. Эта конструкция вместо вызова метода preloadIcons()? Или после нее нужно вызвать preloadIcons() ? Только с ней тоже ничего не обновляется.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)

самое простое - используй таймер (singleShot для запуска или interval для загрузки N иконок за единицу времени - тогда приложение будет подтупливать во время загрузки, но не виснуть)

dib2 ★★★★★
()

Вопрос: Как отловить момент старта exec() в QDialog?

неправильно архитектурно подошел.

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

А как надо было?

У меня все нормально за исключением появления окна. Если бы можно было управлять действиями сразу после exec, вопроса бы не было.

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

Ненормально на самом деле. Хотя и кажется, что нормально. Нужно делать асинхронно, тогда и вопрос с exec() отпадёт.

unC0Rr ★★★★★
()
Ответ на: комментарий от Xintrea
QMetaObject::invokemethod(&dialog,"preloadIcons",Qt::QueuedConnection);
dialog.exec();
anonymous
()
Ответ на: комментарий от Torvus

QTimer::singleShot(0, dialog, SLOT(preloadIcon()));

Ну а если через 0 секунд еще не включится exec() ? Я уже сделал так, но поставил 500мс и думаю, достаточно ли. Или singleShot срабатывает именно в основном цикле диалога? В документации ничего толком не сказано.

Xintrea ★★★★★
() автор топика

Ты пытаешься сделать все через одно место. Нормальные люди делают это через отдельный поток, например через QFuture тот же. Не лепи костылей.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от Xintrea

Читаем документацию QTimer до просветления.

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

Таймер в Qt работает поверх цикла событий, если что.

По этому таймер-0 и вперед.

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

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

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

Шта?! Какие костыли, какая платформа? Мы используем Qt фичу, которая везде работает одинаково.

Про основной поток вообще бред. По словам ТС операция занимает пару сек, и он не знает как сделать ее отложенный запуск, в то время, как вы предлагаете использовать потоки. Зачем?!

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

Шта?! Какие костыли, какая платформа?

Про это ты будешь рассказывать, когда Platform Notes прочитаешь, там четко расписано, где и что работает не так, как у всех.

Мы используем Qt фичу, которая везде работает одинаково.

Когда фичу используют не в том месте, это костыль.

По словам ТС операция занимает пару сек, и он не знает как сделать ее отложенный запуск, в то время, как вы предлагаете использовать потоки. Зачем?!

В данном случае отложенность объясняется желанием применить предложенные костыли. Нормальной практикой является вынос затратных операций в потоки.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от Xintrea

А как надо было?

Exec блокирующий поток, если че.

Надо тебе делать свой метод в диалоге, для отображения.

dia.myexec()

внутри которого ты реализуешь ту процедуру которую хочешь. но тогда exec от QDialog тебе нахер не нужен.

В диалоге надо показывать иконки во вьюхе. А для отображения модель юзать. А заминку с чтением надо анимировать или блокировать вьюху или стеком подменять ее на «ПадаждитеПжалста» и там крутилку. НО главное дать пользователю Cancel этой процедуры. а для того что бы GUI не залип при файловых операциях продолжительных, надо эту тему в отдельный поток выностить. но уже внутри инстанца модели данных.

Не осилишь. могу дать консултацию в шкайпе. контакты у тебя есть.

MikeDM ★★★★★
()
Ответ на: комментарий от MuZHiK-2

Про это ты будешь рассказывать, когда Platform Notes прочитаешь, там четко расписано, где и что работает не так, как у всех.

Где написано что таймер не сработает?

Когда фичу используют не в том месте, это костыль.

Альтернатива?

Нормальной практикой является вынос затратных операций в потоки.

Какие еще затратные операции? ТС нужно загрузить картинки при открытии диалога. Я более чем уверен, что распараллеливании займет больше времени.

И даже если будет быстрее - выигрыш будет мизерный, так как все равно нужно будет отображать QPixmap, который можно создавать только в основном потоке, а значит нужно будет создавать QImage в потоках, затем конвертировать в QPixmap, и его уже отображать. Ну а так да, таймер - это костыль.

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

Где написано что таймер не сработает?

Я и не говорил этого.

Альтернатива?

Не делать костылей.

Какие еще затратные операции? ТС нужно загрузить картинки при открытии диалога. Я более чем уверен, что распараллеливании займет больше времени.

Обращение к жесткому диску для чтения N тысяч файлов уже достаточно затратная операция. А если файл запускается по сети? Такое ощущение, в университетах совсем не учат.

И даже если будет быстрее - выигрыш будет мизерный,

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

так как все равно нужно будет отображать QPixmap, который можно создавать только в основном потоке, а значит нужно будет создавать QImage в потоках, затем конвертировать в QPixmap, и его уже отображать.

Тебя это пугает что ли?

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

A если файл запускается по сети?

Не нужно создавать проблемы там, где их нет.

Не делать костылей.

Ваше решение без костылей в студию.

Такое ощущение, в университетах совсем не учат.

Какой универ, вы о чём?

Я говорил как сделать идеологически правильно, чтобы решение было масштабируемым

ТС нужно открывать фиксированное количество изображений. Я уверен он готов закрыть глаза на тормоза и масштабируемость.

идеологически правильно

Вам лучше не смотреть сорцы ТС.

Тебя это пугает что ли?

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

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

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

ТС сразу надо было ставить тег быдлокод, собственно тогда таймер это детские шалости. Умываю руки.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

Я говорил как сделать идеологически правильно, чтобы решение было масштабируемым

Обоже, для сраного окна диалога со списком иконок делать масштабируемое решение?

С синглшотом задержкой 0 прокатило, тему можно закрывать.

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