Russian Qt Forum
Октябрь 01, 2024, 14:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QProgressDialog , processEvents и QThread  (Прочитано 9806 раз)
polina89
Гость
« : Декабрь 11, 2013, 14:43 »

Здравствуйте!
У меня имеется QProgressDialog, который описывает состояние процесса, идущего в отдельном потоке.При нажатии Cancel пользователю выдается сообщение, действительно ли он хочет остановить процесс. ProgressDialog является немодальным. Все работает как нужно, но после появления QMessageBox по каким-то причинам QProgressDialog вылезает вперед QMessageBox(загораживает его, другими словами).Как это убрать? Это код запуска отдельного потока

Код:
QProgressDialog *ProgressDialog=new QProgressDialog(QObject::trUtf8("Идет экспорт справочников"),QObject::trUtf8("Отмена"),0,100, this);
  ProgressDialog->setWindowFlags(ProgressDialog->windowFlags()&~Qt::WindowContextHelpButtonHint);
  QThread *thread=new QThread();
  workerExp=new LoadingWorkerExp();
  workerExp->moveToThread(thread);
  workerExp->setDefaults(ExportDialog.getFileName(),ExportDialog.getDateTime1(),ExportDialog.getDateTime2());
  connect(thread, SIGNAL(started()), workerExp, SLOT(ExportFunc()));
  /* … и при запуске потока будет вызван метод LoadingProcess(), который обновит БД и  будет работать в новом потоке*/
  connect(workerExp, SIGNAL(finished()), thread, SLOT(quit()));
  /* … и при завершении работы по обновлению БД, обертка  передаст потоку сигнал finished() , вызвав срабатывание слота quit()*/
  connect(workerExp, SIGNAL(finished()), workerExp, SLOT(deleteLater()));
  /* … и обертка пометит себя для удаления при окончании построения отчета*/
  connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
  /* … и поток пометит себя для удаления, по окончании обновления БД. Удаление будет произведено только после полной остановки потока. */
  connect(workerExp,SIGNAL(ValueChanged(int)),ProgressDialog, SLOT(setValue(int)));
  connect(workerExp,SIGNAL(MessageShow()),SLOT(MessageExportSlot()));
 
  connect(workerExp,SIGNAL(StopExporting()),workerExp,SLOT(StopExportProcess()));//вызываем сигнал отмены экспорта
  connect(ProgressDialog,SIGNAL(canceled()),this, SLOT(AskUserExporting()));//спрашиваем, действительно ли пользователь хочет отменить экспорт
  connect(workerExp, SIGNAL(finished()), ProgressDialog, SLOT(cancel()));
  ProgressDialog->show();
  thread->start();
Это схематичный вариант того, что происходит в слоте ExportFunc, т.е. в отдельном потоке

Код:
while ((query.next())&&(stopped))
  {
   value++;
   percentage=(value*100)/count;
   QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   QEventLoop loop; QTimer::singleShot(3000, &loop, SLOT(quit())); loop.exec();
   if (stopped)
   {
    emit ValueChanged(percentage);
   }
  }
  QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
  while ((query2.next())&&(stopped))
  {
   value++;
   percentage=(value*100)/count;
   QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   QEventLoop loop; QTimer::singleShot(3000, &loop, SLOT(quit())); loop.exec();
   if (stopped)
   {
    emit ValueChanged(percentage);
   }
  }
  QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
         while ((query3.next()&&stopped))
  {
                        value++;
   percentage=(value*100)/count;
   QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   if (stopped)
   {
    emit ValueChanged(percentage);
   }
  }
  QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
  file.close();
 }
 if (stopped)
 {
  emit finished();
  emit MessageShow();
 }
 else
 {
 
  emit finished();
 }
Скорее всего дело в ProcessEvents, но точно не могу разобраться.Спасибо большое! Подмигивающий
Записан
Hrundel
Гость
« Ответ #1 : Декабрь 11, 2013, 15:37 »

Наверное QMessageBox нужно в каком-нибудь модусе запускать. Типа information(), warning(), или critical().
Тогда он будет на себе фокус удерживать. А так фокус сразу перехватывает QProgressDialog.
Записан
Bepec
Гость
« Ответ #2 : Декабрь 11, 2013, 16:10 »

Модальность задавайте. Проще говоря в конструкторе укажите ProgressDialog в качестве родителя. А вылезает по той причине, что вы его наверняка с потока обновляете, вот он и лезет.
Записан
polina89
Гость
« Ответ #3 : Декабрь 11, 2013, 16:41 »

Не очень поняла про модальность.Ведь все окна класса QMessageBox уже по умолчанию модальны. Разве нет? Улыбающийся
Записан
Bepec
Гость
« Ответ #4 : Декабрь 11, 2013, 19:48 »

Если им родителя не указать, они не модальны вроде.
Записан
polina89
Гость
« Ответ #5 : Декабрь 12, 2013, 08:20 »

Родителем в моем случае является MainWindow. И QMessageBox является модальным сообщением, так как не дает мне работать, пока я его не закрою.Но это не спасло от того, что ProgressDialog вылезает вперед.Вот код для сообщения Улыбающийся
Код:
        QMessageBox* msgBox = new QMessageBox( this );
msgBox->setStandardButtons(QMessageBox::Ok|QMessageBox::Cancel);
msgBox->setWindowTitle(QObject::trUtf8("Экспорт обновлений справочников" ));
msgBox->setText(QObject::trUtf8("Вы действительно хотите остановить экспорт?"));
msgBox->setIcon(QMessageBox::Warning);
int res=msgBox->exec();
if (res==QMessageBox::Ok)
{
               ...
        }
Записан
Hrundel
Гость
« Ответ #6 : Декабрь 12, 2013, 10:25 »

Попробуй так:

Код
C++ (Qt)
QMessageBox::StandardButton reply;
   reply = QMessageBox::question(this, trUtf8("Экспорт обновлений справочников" ), trUtf8("Вы действительно хотите остановить экспорт?"), QMessageBox::Yes|QMessageBox::No);
 
   if (reply == QMessageBox::Yes)
   {
        // ...  TODO
   }
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Декабрь 12, 2013, 11:04 »

А по-народному сделать ProgressDialog->hide() перед показом QMessageBox? Это и по прынцыпам UI правильно
Записан
polina89
Гость
« Ответ #8 : Декабрь 12, 2013, 11:26 »

К сожалению, ни то, ни другое не помогло.Возможно, это из-за того, что из другого потока посылается сигнал о ходе процесса, который привязан к слоту setValue у ProgressDialog. Но разве при каждом setValue ProgressDialog заново отрисовывается?? и причем еще так, что каким-то образом перекрывает модальное окно Непонимающий Непонимающий Непонимающий
Записан
Hrundel
Гость
« Ответ #9 : Декабрь 12, 2013, 11:35 »

А может у тебя сам ProgressDialog модальный? Попробуй ему явно указать чтобы не был.

Код
C++ (Qt)
progress.setWindowModality(Qt::WindowModal);

Код
C++ (Qt)
// Operation constructor
Operation::Operation(QObject *parent)
    : QObject(parent), steps(0)
{
    pd = new QProgressDialog("Operation in progress.", "Cancel", 0, 100);
    connect(pd, SIGNAL(canceled()), this, SLOT(cancel()));
    t = new QTimer(this);
    connect(t, SIGNAL(timeout()), this, SLOT(perform()));
    t->start(0);
}
 
void Operation::perform()
{
    pd->setValue(steps);
    //... perform one percent of the operation
    steps++;
    if (steps > pd->maximum())
        t->stop();
}
 
void Operation::cancel()
{
    t->stop();
    //... cleanup
}
« Последнее редактирование: Декабрь 12, 2013, 11:44 от Hrundel » Записан
polina89
Гость
« Ответ #10 : Декабрь 12, 2013, 12:17 »

Не помогло. В замешательстве Причем когда ProgressDialog вылезает вперед мне недоступна кнопка "Отмена", так как она блокируется модальным QMessageBox. Но почему тогда этот Dialog лезет вперед, я ума не приложу.
Записан
Dima
Гость
« Ответ #11 : Декабрь 12, 2013, 12:34 »

сделайте ProgressDialog  родителем для месседжа
Записан
Hrundel
Гость
« Ответ #12 : Декабрь 12, 2013, 14:41 »

Да делала она уже.

Просто процесс всегда фокус перехватывает. Не понятно как-то. Наверное, тебе придется больше кода показать, а то теперь совсем трудно понять в чем проблемма.
Записан
polina89
Гость
« Ответ #13 : Декабрь 12, 2013, 14:57 »

Спасибо всем большое за помощь!=)Получилось сделать с родителем)Изначально не вышло, потому что там был еще мой собственный косяк, точнее недочет)Так что теперь все гуд.Спасибо!!! Веселый Веселый Веселый Веселый Веселый
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.188 секунд. Запросов: 23.