Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Displaying a Large PDF without Freezing the UI Thread
Qt 6.11 is out! See what's new in the release blog

Displaying a Large PDF without Freezing the UI Thread

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
7 Posts 3 Posters 1.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Serhan KarsS Offline
    Serhan KarsS Offline
    Serhan Kars
    wrote on last edited by Serhan Kars
    #1

    Hi everyone,

    I am having some problems displaying a large PDF file using a Loader. I have a sample code below:

    When the Load button is pressed in the code below, a large PDF file is displayed using PdfMultiPageView. I also make an AnimatedImage visible when the Loader is loading the component. However, since the PDF is a large file, the UI thread probably freezes when creating the PDF elements.

    Do you have any suggestions for cases like this?

    I am aware that using Qt.callLater is useful for operations with loops that take a long time, but this case is a little bit different.

    Thanks in advance.

    import QtQuick
    import QtQuick.Pdf
    import QtQuick.Controls
    
    Window {
        width: 500
        height: 500
    
        visible: true
        title: "PdfTest"
    
        Rectangle {
            anchors.fill:parent
    
            Loader{
                id: loader
                anchors.fill: parent
                asynchronous: true
                sourceComponent: undefined
                onLoaded: loadingImg.visible = false
            }
    
            Component{
                id: pmvComp
                PdfMultiPageView{
                    document: PdfDocument{ source: 'LARGE_PDF_FILE.pdf'} // some Pdf with 20 MB size
                }
            }
    
            AnimatedImage {
                id: loadingImg
                anchors.centerIn: parent
                source: "loading.gif"
                width:50
                height:50
                visible:false
            }
    
            Button{
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.bottom: parent.bottom
                anchors.bottomMargin: 10
    
                text: loader.sourceComponent == undefined ?  "Load":"Unload"
                onClicked: {
    
                        if(loader.sourceComponent == undefined){
                            loadingImg.visible = true
                            loader.sourceComponent = pmvComp
                        }
                        else{
                            loader.sourceComponent = undefined
                        }
                }
            }
        }
    
    }
    
    1 Reply Last reply
    0
    • B Offline
      B Offline
      Bubu-Droid
      wrote last edited by
      #2

      Hey, can someone please reply to this? I'm trying to load a PDF in a Qt Widget application using threading. Irrespective of what I do, it fails to load the PDF. I tried creating a concurrent thread, made a new QPdfDocument, loaded a PDF into the entity and then moved it to the main thread before returning the pointer. It still doesn't work! Here is an MWE (I know that the PDF loading in this example is synchronous, but even this fails to work - forget about loading the PDF asynchronously):

        QFuture<QPdfDocument*> future = QtConcurrent::run([](){
          QPdfDocument* loadDoc = new QPdfDocument();
          loadDoc->load(ProjectSettings::instance().pdfPath);
          loadDoc->moveToThread(QApplication::instance()->thread());
          return loadDoc;
        });
      
        m_document = future.result();
      
      JonBJ 1 Reply Last reply
      0
      • B Bubu-Droid

        Hey, can someone please reply to this? I'm trying to load a PDF in a Qt Widget application using threading. Irrespective of what I do, it fails to load the PDF. I tried creating a concurrent thread, made a new QPdfDocument, loaded a PDF into the entity and then moved it to the main thread before returning the pointer. It still doesn't work! Here is an MWE (I know that the PDF loading in this example is synchronous, but even this fails to work - forget about loading the PDF asynchronously):

          QFuture<QPdfDocument*> future = QtConcurrent::run([](){
            QPdfDocument* loadDoc = new QPdfDocument();
            loadDoc->load(ProjectSettings::instance().pdfPath);
            loadDoc->moveToThread(QApplication::instance()->thread());
            return loadDoc;
          });
        
          m_document = future.result();
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote last edited by JonB
        #3

        @Bubu-Droid
        Obviously to start with:

        • QPdfDocument::Error QPdfDocument::error() const (and statusChanged(QPdfDocument::Status status)). This is vital and first thing you should check.
        • Verify ProjectSettings::instance().pdfPath exists.
        • Have you tried multiple/absolute minimal PDF documents?
        • Get rid of any concurrency/moveToThread.
        • Is it safe/sensible to call loadDoc->moveToThread() while loadDoc->load() is running? Even if it is allowed, why/what is the effect of setting off a load before moving to a thread?
        B 1 Reply Last reply
        0
        • JonBJ JonB

          @Bubu-Droid
          Obviously to start with:

          • QPdfDocument::Error QPdfDocument::error() const (and statusChanged(QPdfDocument::Status status)). This is vital and first thing you should check.
          • Verify ProjectSettings::instance().pdfPath exists.
          • Have you tried multiple/absolute minimal PDF documents?
          • Get rid of any concurrency/moveToThread.
          • Is it safe/sensible to call loadDoc->moveToThread() while loadDoc->load() is running? Even if it is allowed, why/what is the effect of setting off a load before moving to a thread?
          B Offline
          B Offline
          Bubu-Droid
          wrote last edited by Bubu-Droid
          #4

          @JonB

          The PDF path does exist. I've removed the entire threading logic and I'm currently trying to load the PDF document in the main thread. I tried adding a print statement just after pdfDocument->load() for debugging purposes and noticed that the statement gets printed immediately even though the PDF has not finished loading yet and the UI is frozen.

          What I want to avoid is the freezing of UI when I'm trying to load a large PDF. I'm using X11 as my display server.

          The pdfviewer project in Qt examples has the same problem. The UI freezes when I'm trying to load a large PDF.

          qDebug() << ProjectSettings::instance().pdfDocument->status();

          I added this after the load() statement to check what the result is. It's weird that this returns READY even though the UI remains frozen.

          JonBJ 2 Replies Last reply
          0
          • B Bubu-Droid

            @JonB

            The PDF path does exist. I've removed the entire threading logic and I'm currently trying to load the PDF document in the main thread. I tried adding a print statement just after pdfDocument->load() for debugging purposes and noticed that the statement gets printed immediately even though the PDF has not finished loading yet and the UI is frozen.

            What I want to avoid is the freezing of UI when I'm trying to load a large PDF. I'm using X11 as my display server.

            The pdfviewer project in Qt examples has the same problem. The UI freezes when I'm trying to load a large PDF.

            qDebug() << ProjectSettings::instance().pdfDocument->status();

            I added this after the load() statement to check what the result is. It's weird that this returns READY even though the UI remains frozen.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote last edited by JonB
            #5

            @Bubu-Droid
            Initially you wrote

            it fails to load the PDF

            Now you say

            What I want to avoid is the freezing of UI when I'm trying to load a large PDF

            Which is the case? Does it fail to load the PDF and you should be looking at error() or does it take rather longer than you want and possibly interfere with UI's responsiveness but if you went and made a coffee it would complete by the time you returned? These are two very different situations.

            1 Reply Last reply
            0
            • B Bubu-Droid

              @JonB

              The PDF path does exist. I've removed the entire threading logic and I'm currently trying to load the PDF document in the main thread. I tried adding a print statement just after pdfDocument->load() for debugging purposes and noticed that the statement gets printed immediately even though the PDF has not finished loading yet and the UI is frozen.

              What I want to avoid is the freezing of UI when I'm trying to load a large PDF. I'm using X11 as my display server.

              The pdfviewer project in Qt examples has the same problem. The UI freezes when I'm trying to load a large PDF.

              qDebug() << ProjectSettings::instance().pdfDocument->status();

              I added this after the load() statement to check what the result is. It's weird that this returns READY even though the UI remains frozen.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote last edited by JonB
              #6

              @Bubu-Droid said in Displaying a Large PDF without Freezing the UI Thread:

              qDebug() << ProjectSettings::instance().pdfDocument->status();

              I added this after the load() statement to check what the result is. It's weird that this returns READY even though the UI remains frozen.

              You just added this. load() is asynchronous. You should start by placing a slot on statusChanged(QPdfDocument::Status status) to see what is happening. Does that show loading and then ready or error or never gets to either?

              B 1 Reply Last reply
              0
              • JonBJ JonB

                @Bubu-Droid said in Displaying a Large PDF without Freezing the UI Thread:

                qDebug() << ProjectSettings::instance().pdfDocument->status();

                I added this after the load() statement to check what the result is. It's weird that this returns READY even though the UI remains frozen.

                You just added this. load() is asynchronous. You should start by placing a slot on statusChanged(QPdfDocument::Status status) to see what is happening. Does that show loading and then ready or error or never gets to either?

                B Offline
                B Offline
                Bubu-Droid
                wrote last edited by Bubu-Droid
                #7

                @JonB

                Hey, I've figured out the cause. It's being caused by the thumbnail rendering. I commented out the line

                  ui->thumbnailView->setModel(pdfDocument->pageModel());
                

                and the PDF is loaded instantly. Maybe loading the thumbnails on a different thread won't freeze the UI? (setModel isn't thread safe it seems). The setModel probably causing problems since the pdfDocument->pageModel() is huge. Can you please help me out with how I could fix this? The thumbnailView is a QListView btw.

                EDIT: I've set setUniformItemSizes to true and the loading is much faster now (almost instantaneous).

                ui->thumbnailView->setUniformItemSizes(true);
                

                I think this was the key to making the view load its items faster. But the scrolling in the thumbnailView widget is pretty laggy.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved