LINUX.ORG.RU

Зависает GUI во время построения графика и расчётов(Qt5)

 , ,


0

1

Здравствуйте, у меня такая проблема Приложение делает расчёты и выводит сразу на экран( 2 графика + Colorplot). Для отрисовки использую Qcustomplot. Я даже сами расчёты в отдельный поток засунул, и всё равно GUI inactive пока идут расчёты и рисуются графики(

Вот та часть кода, в которой и происходит расчёт и прорисовка графиков

 
 void MainWindow::on_go_clicked()
{
    //инициализация текстовых файлов
    //некоторые переменные для норм работы проги
    //инициализация графиков
    ui->caSSplot->clearGraphs();
    ui->CajSRplot->clearGraphs();
    //ui->Perplot->clearPlottables();
    ui->caSSplot->addGraph();
    ui->caSSplot->yAxis->setLabel("CaSS, microM");
    ui->caSSplot->xAxis->setLabel("time,ms");
    ui->CajSRplot->addGraph();
    ui->CajSRplot->yAxis->setLabel("CajSR, microM");
    ui->CajSRplot->xAxis->setLabel("time,ms");
    //инициализация colorMap'a
    QCPColorMap *colorMap = new QCPColorMap(ui->Perplot->xAxis, ui->Perplot->yAxis);
    ui->Perplot->addPlottable(colorMap);
    int nx = ui->RyRSize->value();
    int ny = ui->RyRSize->value();
    colorMap->data()->setSize(nx, ny);
    QCPColorScale *colorScale = new QCPColorScale(ui->Perplot);
    ui->Perplot->plotLayout()->addElement(0, 1, colorScale); 
    colorScale->setType(QCPAxis::atRight); 
    colorMap->setColorScale(colorScale);
    colorScale->axis()->setLabel("Lattice permittivity");
    for (int xIndex=0; xIndex < nx; ++xIndex)
    {
      for (int yIndex=0; yIndex < ny; ++yIndex)
      {
        colorMap->data()->cellToCoord(xIndex, yIndex, 0, 0);
      }
    }
    //готовимся к расчётам(инициализация переменных модели)
    //собственно, расчёт
    for(int i = 1; i*dt <= t; ++i){
        if(stop) break;
        //готовим данные для графиков
        double omptime = omp_get_wtime();
        SSdata = clock.getCaSS();
        jSRdata = clock.getCajSR();
        for(int j = 0; j < clusterdata.size(); ++j)
            for(int z = 0; z < clusterdata.size(); ++z)
                clusterdata[j].push_back(cluster.lattice[j][z].Permittivity());
        //запускаем отдельный поток под итерацию
        QFuture<void> future =  QtConcurrent::run(this,&MainWindow::computation,dt);
        //пишем графики
        drawjSR((i-1)*dt,jSRdata);
        drawSS((i-1)*dt,SSdata);
        drawper(clusterdata,colorMap);
    }
    delete colorScale;
    delete colorMap;
//..
}

т.е. графики нормально рисуются, расчёты идут правильно, но GUI замораживается(


попробуйте для начала, скажем, в конец цикла (после drawper(clusterdata,colorMap)) вставить qApp->processEvents()

может полегчает %)

metawishmaster ★★★ ()
Ответ на: комментарий от metawishmaster

Действительно заработало, спасибо огромное!

Hi4ko ()

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

grondek ()
Ответ на: комментарий от grondek

по-хорошему бы тяжелые вычисления выносить в отдельный поток

да тут так и получается:

//запускаем отдельный поток под итерацию
QFuture<void> future =  QtConcurrent::run(this,&MainWindow::computation,dt);

metawishmaster ★★★ ()
Ответ на: комментарий от metawishmaster

Как правило в приложении используются или расчёты в отдельном потоке (QtConcurrent::run), или периодическая обработка событий в цикле рассчёта через qApp->processEvents()

Использование и того и другого - признак ошибки в архитектуре или в реализации.

Я никогда не пользовался именно QFuture, но вообще после асинхронных операций обычно назначаются callback-и, которые уже и обрабатывают результат рассчётов в UI-потоке.

Здесь же QFuture<void> future никак не используется после определения, что выглядит очень похожим на ошибку.

Как будто бы результаты расчётов используются когда-то потом, неявно, и просто «везёт» что к моменту их использования они уже готовы.

GPFault ()
Ответ на: комментарий от metawishmaster

Эта хрень ждёт завершения выполнения. Пока не получит сигнал о завершении то главный поток будет ожидать. Для этого нужно использовать qfuturewatcher. UPD: попробуй после QFuture<void> future вставить строчку future.waitForFinished();

CrazyAlex25 ★★ ()
Последнее исправление: CrazyAlex25 (всего исправлений: 1)
Ответ на: комментарий от GPFault

пардон, забыл... у меня в коде есть и future.waitForFinished(), и без qApp->processEvents() не обошлось

metawishmaster ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.