1

I try to update progress bar value by QFutureWatcher signals like this:

QObject::connect(
    &imageCreating_, &QFutureWatcher<void>::finished,
    loader, &Loader::creatingImagesFinished
);

QObject::connect(
    &imageCreating_, &QFutureWatcher<void>::progressRangeChanged,
    loader, &Loader::setRange
);

QObject::connect(
    &imageCreating_, &QFutureWatcher<void>::progressValueChanged,
    loader, &Loader::setValue
);

imageCreating_.setFuture(QtConcurrent::map(items_, updateImage));

But signals progressRangeChanged and progressValueChanged fire only once at the beginning and both are zero. So range is (0, 0) and value is 0.

Finished signal works as expected when the computation is complete.

What am I doing wrong?

============= updated: Here is the code of my test example. When I wrote it I found that problem is in using QMap container. When I'm using QVector all works fine, but when I'm using QMap the problem has occur. Is it possible to get progress values using QMap?

#include <QtWidgets>
#include <QtConcurrent>

using namespace QtConcurrent;

typedef struct {
    /*....*/
    QImage* image;
} Item;

void burnTextImage(Item& item)
{
    QImage* img = new QImage("D:/Projects/Sortition/res/img/document260x195.png");

    QPainter p (img);
    p.drawText(QRect(10, 10, 200, 145), "some text");
    item.image = img;
}

void spin(int &iteration)
{
    const int work = 9999999;
    volatile int v = 0;
    for (int j = 0; j < work; ++j)
        ++v;
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QMap<int, Item> items_;
    //QVector<Item> items_;
    //QVector<int> vector;
    for (int i = 0; i < 20000; ++i) {
        Item item;
        item.image = 0;
        items_.insert(i, item);
        //items_.append(item);
        //vector.append(i);
    }

    QProgressDialog dialog;
    dialog.setLabelText(QString("Progressing using %1 thread(s)...").arg(QThread::idealThreadCount()));

    QFutureWatcher<void> imageCreating_;
    QObject::connect(&imageCreating_, SIGNAL(finished()), &dialog, SLOT(reset()));
    QObject::connect(&dialog, SIGNAL(canceled()), &imageCreating_, SLOT(cancel()));
    QObject::connect(&imageCreating_, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int)));
    QObject::connect(&imageCreating_, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));

    imageCreating_.setFuture(QtConcurrent::map(items_, burnTextImage));
    //imageCreating_.setFuture(QtConcurrent::map(vector, spin));

    dialog.exec();

    imageCreating_.waitForFinished();

    qDebug() << "Canceled?" << imageCreating_.future().isCanceled();
}

====== updaited again: I'm sorry, I found in Qt documentation that progress information is provided only for random access iterator. Clearly that QMap is not such container. What type I can use instead?

Sergey
  • 144
  • 1
  • 13
  • Seems like the problem isn't in the code you posted. – thuga Mar 06 '15 at 13:10
  • Does your future signal progress? We'd need to see its code. The future won't automatically do it for you, it's up to you to do it. – Kuba hasn't forgotten Monica Mar 06 '15 at 16:38
  • 1
    If you received the `QFuture` from `QtConcurrent::run()`, note that this function doesn't support progress reporting. See http://doc.qt.io/qt-5/qtconcurrent.html#run – RA. Mar 06 '15 at 21:58

0 Answers0