Lazy Loading para uma QScrollArea



  • Estou fazendo um leitor de pdf utilizando a biblioteca poppler, basicamente o funcionamento é pegar cada página e renderizar em um QImage, essas imagens serão adicionadas a um layout, que por sua vez seria adicionado a uma inner widget de um QScrollArea, O código de testes está logo abaixo:

    #include "mainwindow.h"
    #include <QApplication>
    #include <QLabel>
    #include <QGridLayout>
    #include <QWidget>
    #include <QScrollArea>
    #include <QScrollBar>
    #include <QDebug>
    
    #include <poppler/qt5/poppler-qt5.h>
    
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
    
    
    
        QString filename = "/home/gustavo/Downloads/notas-2015.2.pdf";
        Poppler::Document* document = Poppler::Document::load(filename);
        if (!document || document->isLocked()) {
         // ... error message ....
         delete document;
         return 1;
        }
    
        // Paranoid safety check
        if (document == 0) {
          // ... error message ...
          return 1;
        }
    
        QScrollArea *scrollArea = new QScrollArea;
        QWidget *scrollWidget = new QWidget;
    
        scrollWidget->setLayout(new QGridLayout);
        scrollArea->setWidget(scrollWidget);
        
        int numPages = document->numPages();
    
        
        
        for(int i = 0; i < numPages; ++i)
        {
            Poppler::Page* pdfPage = document->page(i);  
            if (pdfPage == 0) {
    
             return 1;
             }
    
    
             QImage image = pdfPage->renderToImage(200,200,-1,-1,-1,-1);
            if (image.isNull()) {
                // ... error message ...
               return 1;
          }
    
    
             QLabel *label = new QLabel;
             label->setPixmap(QPixmap::fromImage(image));
             label->setAlignment( Qt::AlignCenter );
    
             scrollWidget->layout()->addWidget(label);
    
             delete pdfPage;
        }
    
        scrollArea->setWidgetResizable(true);
        w.setCentralWidget(scrollArea);
    
    
    
    
        w.show();
    
        delete document;
    
        return a.exec();
    }
    ```
    ```
    
    Mas tem um problema, se o pdf for muito grande, ele vai simplismente travar o computador, devido ao grande consumo de memória, já que vou carregar todas as páginas de uma vez na tela. Como eu faria um lazy loading com issoCaso não seja possível, como eu carregaria ao longo que o usuário desce o scroll?


  • Você pode usar um QFutureWatcher, que faz parte do pacote Qt Concurrent.

    Você vai fazer a função que transforma o PDF em imagens, e em vez de chamar diretamente, vai usar o QFutureWatcher para saber que acabou através do slot handleFinished(), como está no exemplo (e abaixo).

    // Instantiate the objects and connect to the finished signal.
    MyClass myObject;
    QFutureWatcher<int> watcher;
    connect(&watcher, SIGNAL(finished()), &myObject, SLOT(handleFinished()));
    
    // Start the computation.
    QFuture<int> future = QtConcurrent::run(pdf2image, QString("pdf?"));
    watcher.setFuture(future);
    


  • Aqui tem um exemplo do Qt Concurrent



  • @TioRoy Obrigado, serviu aqui!



  • Depois altera o título do post para 'SOLVED' :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.