необъяснимая задержка после завершения загрузки QProgressBar

У меня есть сигнал от цикла (который делает некоторые вычисления), который запускает обновление индикатора выполнения, который находится в главном графическом интерфейсе, после завершения цикла индикатор выполнения обновляется до 100% (индикатор выполнения становится скрытым после завершения процесса), но затем есть задержка, индикатор выполнения остается на 100%, а иногда мышь становится занятой, и только через несколько секунд индикатор выполнения становится скрытым (указывает, что задержка заканчивается), после этого цикла ничего не происходит, поэтому я ничего не могу думает может сделать эту задержку.

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

Сигнал излучения находится внутри класса в логическом слое, я должен попробовать что-то, включая <QtGui/QApplication> в этот класс (что звучит для меня не правильно, так как это логический уровень, так зачем ему нужны библиотеки QtGui, но я только что-то тестирую), я поместил следующий код qApp->processEvents(); внутри цикла, и теперь кажется, что все работает задушено, нет занятой мыши, но все равно есть задержка (единственное, что я могу реагировать с GUI, пока происходит эта задержка, но нет обновленных результатов, пока эта задержка не закончится).

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

Пример кода:

Класс логического слоя:

#include <QtGui/QApplication>
...

processMethod(...)
{
Loop(...)
{
qApp->processEvents();
emit processBarSignle(value);
...some calculations...
}
emit processBarSignle(100);
}

Вид слоя (MainWindow):

on_btn_nextProcess_clicked()
{
m_ui->pBar_process->setVisible(true);
LogicClass->processMethod(...);
m_ui->pBar_process->setVisible(false);
}

Спасибо

1

Решение

Попробуйте следующее:

#include <QtCore/QCoreApplication>
...

processMethod(...)
{
Loop(...)
{
emit processBarSignle(value);
QCoreApplication::processEvents();
...some calculations...
}
emit processBarSignle(100);
QCoreApplication::processEvents();
}

processEvents() статический метод QCoreApplication, так достаточно включить только QCoreApplication которая является частью QtCore библиотека.

Кроме того, вы должны добавить processEvents() после обновления индикатора выполнения, а не до этого.

Обратите внимание, что processEvents() не возвращается, пока не будет обработано каждое событие в очереди событий Qt. Если есть, например, Cancel Кнопка, вам придется проверить, действительно ли пользователь отменил операцию каждый раз, когда вы звонили processEvents(),
Вы можете исключить пользовательские события, такие как щелчки мыши / нажатия клавиш, используя

QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents )

но это не позволит нажимать что-либо (например, кнопку «Отмена»), когда цикл активен.

Как дальнейшее примечание: это должно называться «processBarSi нг le «;-)


Уточнение по темам и т.д:

Весь ваш цикл и любые щелчки мышью и т. Д. Выполняются только в одном потоке. Если вы позвоните emit(), slot что связано с этим signal выполняется мгновенно (если слот не был на самом деле в другом потоке). А пока цикл не продолжается!

Когда слот закончится, ваш цикл продолжится. В моем примере это означает processEvents() будет вызван. Теперь, если ваш слот обновил индикатор выполнения или сделал что-то еще, что вызвало перерисовку, в очереди событий будет событие перерисовки, и теперь эта перерисовка произойдет.
Если вы выполните processEvents() перед вызовом вашего слота не будет никакого события перерисовки, которое можно было бы обработать в этот момент.

Еще раз, цикл не продолжается до processEvents() полностью сделано. Когда все ожидающие события были обработаны, цикл продолжается с вашими расчетами.

0

Другие решения

В вашем примере кода фактически есть только один поток. когда on_btn_nextProcess_clicked() вызывается, показывает индикатор выполнения, затем запускается processMethod() в той же теме. В идеале вы хотите разделить ваш пользовательский интерфейс и логику обработки данных.

В инициализации создайте отдельный QThread, запустите его и переместите объект LogicClass в этот поток, вызвав logicClassObject-> moveToThread ([ваш новый поток]). Затем поверните processMethod() в слот, создайте startProcessing() сигнал в MainWindow и соедините их. Наконец, создайте processingDone() слот в MainWindow и finishedProcessing() слот в LogicClass и соединить их. Когда все это настроено, вы можете изменить свой код следующим образом:

void LogicClass::processMethod(...)
{
Loop(...)
{
emit processBarSignal(value);
...some calculations...
}
emit processingDone();
}

void MainWindow::on_btn_nextProcess_clicked()
{
m_ui->pBar_process->setVisible(true);
emit startProcessing(...);
}

void MainWindow::finishedProcessing()
{
m_ui->pBar_process->setVisible(false);
}

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

В этом случае поток пользовательского интерфейса запланирует событие в потоке обработки, чтобы начать обработку. Затем поток обработки будет постоянно планировать обновления значений progressBar и, наконец, планировать событие, чтобы отключить индикатор выполнения после его завершения. Два потока будут работать в соответствии с планировщиком потока ОС, и обработка не будет блокировать пользовательский интерфейс.

0

По вопросам рекламы [email protected]