Как? Я показываю сообщение во время выполнения задачи

#c #qt

Вопрос:

У меня есть следующий код.

Метод compress (), в котором я выполняю задачу сжатия всего каталога, я вызываю этот метод из своей кнопки с помощью QtConcurrent, как вы можете видеть. пока все хорошо.

Мой вопрос в том, как я могу отобразить сообщение во время выполнения сжатия папки.

Я использую QuaZIP для процесса сжатия.

 #ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
  Q_OBJECT

public:
  Widget(QWidget *parent = nullptr);
  ~Widget();
 
private slots:
  void on_pushButton_5_clicked();

private:
  Ui::Widget *ui;
  void compress();
public:
 
};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QDebug>
#include <JlCompress.h>
#include <QtConcurrent/QtConcurrent>
#include <QFuture>

Widget::Widget(QWidget *parent)
  : QWidget(parent), ui(new Ui::Widget)
{
  ui->setupUi(this); 
}
Widget::~Widget()
{
  delete ui;
}
void Widget::on_pushButton_5_clicked()
{
  QGuiApplication::setOverrideCursor(Qt::WaitCursor);
  QFuture<void> future=QtConcurrent::run(this,amp;Widget::compress);
  future.waitForFinished();
  QGuiApplication::restoreOverrideCursor();
  QMessageBox::information(this,qApp->applicationName(),"The folder was compressed successfully.");
}
void Widget::compress()
{
  if(!JlCompress::compressDir("C:/Users/Mypc/Desktop/iconos.zip", "D:/images/iconos")){
    QMessageBox::warning(this,qApp->applicationName(),"Error compressing folder.");
    return;
  }
}
 

Я сделал это, но теперь, когда резервное копирование завершено, все приложение закрывается.

     void Widget::on_pushButton_5_clicked()
    {
      
      QMessageBox box;
  //  box->setWindowFlags(Qt::Dialog | Qt::SplashScreen);
  box.setStandardButtons(QMessageBox::NoButton);
  box.setText("Realizando una tarea!");
  box.setWindowTitle(qApp->applicationName());
  box.setIcon(QMessageBox::Information);
  box.setAttribute(Qt::WA_DeleteOnClose);

  QFutureWatcher<void> watcher;

  QFuture<void> future=QtConcurrent::run(this,amp;Widget::compress);
  watcher.setFuture(future);

  QGuiApplication::setOverrideCursor(Qt::WaitCursor);

  QObject::connect(amp;watcher,amp;QFutureWatcher<void>::finished,[amp;](){

    box.close();
    box.deleteLater();
    QGuiApplication::restoreOverrideCursor();
  });
  box.exec();
      QMessageBox::information(this,qApp->applicationName(), "The folder was compressed successfully.");
    
    }
 

Также попробуйте ProgressDialog и QFutureWatcher следующим образом, но он не компилируется, я получаю эту ошибку.

введите описание изображения здесь

 void Widget::on_pushButton_5_clicked()
{

  QStringList files;
  QDir dir("D:/images/iconos/uigenericicon");
  files=dir.entryList(QStringList() << "*.jpg" << "*.JPG"<<"*.PNG",QDir::Files);
  
  qInfo()<<files;

  QProgressDialog pDialog;
  pDialog.setLabelText("Porecessing!!");

  QFutureWatcher<void> watcher;

  QObject::connect(amp;pDialog,SIGNAL(canceled()),amp;watcher,SLOT(cancel()));
  QObject::connect(amp;watcher,SIGNAL(finished()),amp;pDialog,SLOT(reset()));
  QObject::connect(amp;watcher,SIGNAL(progressRangeChanged(int,int)),amp;pDialog,SLOT(setRange(int,int)));
  QObject::connect(amp;watcher,SIGNAL(progressValueChanged(int)),amp;pDialog,SLOT(setValue(int)));

  watcher.setFuture(QtConcurrent::map(files,amp;Widget::compress));
  pDialog.exec();
  if(watcher.isCanceled()){
    QMessageBox::information(this,qApp->applicationName(),"You canceled.");
  }else{
    QMessageBox::information(this,qApp->applicationName(),"All done.");
  }
}

void Widget::compress(QStringList amp;files)
{

  if(!JlCompress::compressFiles("C:/Users/Lincoln/Desktop/iconos.zip",files)){
    QMessageBox::warning(this,qApp->applicationName(),"Error al comprimir la carpeta.");
    return;
  }

}
 

Комментарии:

1. Вы ищете неблокирующий QMessageBox?

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

3. Вам нужно избавиться от future.waitForFinished(); этого, чтобы графический интерфейс не обновлялся до тех пор, пока выполняется параллельное задание. Помните, что графический интерфейс не будет обновляться до тех пор, пока он не выйдет из вашей функции и не вернется в цикл событий. Ваш QMessageBox также может быть проблематичным в том, что вы должны отображать это в потоке графического интерфейса, а не в рабочем.

4. Если вы хотите использовать QtConcurrent, вам может потребоваться: https://doc.qt.io/qt-5/qfuturewatcher.html

5. if(watcher.isCanceled()){ Деталь должна быть в функции reset ().