Есть ли способ использовать 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()
(что также чище, чем предоставление обратных вызовов).
Теперь вы можете обернуть весь этот код в функцию, которая сама по себе будет блокирующим вызовом, поэтому при желании он может вернуть некоторые результаты из вашего диалога.