Есть ли способ использовать Qt без QApplication::exec()?

Есть ли безопасный способ использовать Qt без вызова QApplication::exec()?

У меня есть несколько различных объектов, которые выполняют долгоживущие процессы на нескольких ресурсах (по крайней мере, один из них взаимодействует с сервером веб-приложений). Я делаю приложение с графическим интерфейсом, которое запрашивает ввод у пользователя в нужное время для этих различных процессов. Я хотел бы иметь мою логику "потока" - логику, которая определяет, что делать дальше - в одном месте, а не в объекте GUI, таком как класс диалога. Я думал, что я мог бы сделать что-то вроде этого:

...

wait_dialog dlg;
dlg.setModal( false );
dlg.show(); // Should return...

netobject.start_long_lived_process_that_happens_on_other_thread( &completion_callback );
while ( !completion_callback_called() )
{
    qApp->processEvents();
    netobject.pump_callbacks();
    magically_avoid_busywait_while_still_servicing_qt_somehow();
}

dlg.hide();

...

Это безопасно с точки зрения Qt? Есть ли "хороший" способ реализации magically_avoid_busywait_while_still_servicing_qt_somehow()?

То, что я пытаюсь сделать здесь, - это написать наш процесс обработки максимально понятным способом. Я хотел бы одну функцию, которая делает это:

 show_a_non_modal_wait_dialog()

 start_some_processing_1()

 wait_for_processing_1_to_finish()

 dismiss_non_modal_wait_dialog()

 show_modal_input_dialog()

 if ( cancelled ) return

 show_a_non_modal_wait_dialog()

 start_some_processing_2()

 wait_for_processing_2_to_finish()

 dismiss_non_modal_wait_dialog()

 show_modal_input_dialog()

 if ( cancelled ) return

 ...

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

1 ответ

Решение

То, что вы хотите, это цикл событий, отличный от основного цикла событий приложения. Это можно сделать с помощью QEventLoop:

wait_dialog dlg;
dlg.setModal( false );
dlg.show(); // Should return...

QEventLoop loop;
connect(&netobject, SIGNAL(done()), &loop, SLOT(quit()));
netobject.start_long_lived_process_that_happens_on_other_thread();

loop.exec(); // BLOCKING (non-busy) until quit() is called via the signal done()

Хотя это (на мой взгляд) чистый код, для этого требуется, чтобы ваш класс netobject был QObject и реализовывал сигнал done() (что также чище, чем предоставление обратных вызовов).

Теперь вы можете обернуть весь этот код в функцию, которая сама по себе будет блокирующим вызовом, поэтому при желании он может вернуть некоторые результаты из вашего диалога.

Другие вопросы по тегам