Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Solved Not able to render a tableview to pdf.

    General and Desktop
    qprinter painter rendering qt desktop
    5
    9
    470
    Loading More Posts
    • 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.
    • S
      sachinrd last edited by sachinrd

      hello,
      I am a newbie in qt, and i was trying to render a table view to a pdf using printers. Below is the reduced version of the code and i am not able to achieve it. can someone help me with this. Thanks for any help in advance.

          ui->setupUi(this);
      
          QStandardItemModel *indexPageModel=new QStandardItemModel;
          QTableView *indexPageTableView=new QTableView();
          indexPageTableView->setModel(indexPageModel);
          indexPageTableView->verticalHeader()->setVisible(false);
          indexPageTableView->horizontalHeader()->setVisible(false);
      //populate tableview
      //row1
          QStandardItem *item00 = new QStandardItem("   Title  ");
          item00->setTextAlignment(Qt::AlignCenter);
          indexPageModel->setItem(0, 0, item00);
      
          QStandardItem *item01 = new QStandardItem("  X-axis  ");
          item01->setTextAlignment(Qt::AlignCenter);
          indexPageModel->setItem(0, 1, item01);
      
          QStandardItem *item02 = new QStandardItem("  Y-axis  ");
          item02->setTextAlignment(Qt::AlignCenter);
          indexPageModel->setItem(0, 2, item02);
      
          QStandardItem *item03 = new QStandardItem("    Page#    ");
          item03->setTextAlignment(Qt::AlignCenter);
          indexPageModel->setItem(0, 3, item03);
      
          QStandardItem *item04 = new QStandardItem("    Trend#    ");
          item04->setTextAlignment(Qt::AlignCenter);
          indexPageModel->setItem(0, 4, item04);
      
          QStandardItem *item05 = new QStandardItem("Trend Relationship");
          item05->setTextAlignment(Qt::AlignCenter);
          indexPageModel->setItem(0, 5, item05);
      
          indexPageTableView->resizeColumnsToContents();
      
          QGraphicsScene *scene=new QGraphicsScene(this);
          QGraphicsProxyWidget *proxy = scene->addWidget(indexPageTableView);
          ui->graphicsView->setScene(scene);
          ui->graphicsView->setAlignment(Qt::AlignTop | Qt::AlignLeft);
      
      
          int width = (indexPageModel->columnCount() - 1) + indexPageTableView->verticalHeader()->width();
               for (int column = 0; column < indexPageModel->columnCount(); column++)
                   width = width + indexPageTableView->columnWidth(column);
         indexPageTableView->setMinimumWidth(width);
      //tableview populated
      
      //render tablview to a pdf
         QFileDialog dialog(this);
         dialog.setDefaultSuffix("pdf");
         QString pdffileName = dialog.getSaveFileName(this, tr("Save File"),
                                                    "doc.pdf",
                                                    tr("file(.pdf)"));
      
         QPixmap pixIndexPage(indexPageTableView->size());
         pixIndexPage.fill(Qt::transparent);
         QPainter painterIndexPage(&pixIndexPage);
         painterIndexPage.setRenderHints(QPainter::LosslessImageRendering,QPainter::HighQualityAntialiasing);
         indexPageTableView->render(&painterIndexPage);
      
         QPrinter printer;
         printer.setOutputFileName(pdffileName);
         printer.setFullPage(true);
         printer.setPageSize(QPageSize(QPageSize::A4));
         printer.newPage();
         QPainter painter( &printer);
      
         const QRectF textRect(0, 0, printer.pageRect().width() ,printer.pageRect().height() );
         painter.setClipRect(textRect);
         painter.drawPixmap(textRect,pixIndexPage,QRect(0,0,pixIndexPage.size().width(),pixIndexPage.size().height()));```
      JonB artwaw 2 Replies Last reply Reply Quote 0
      • mrjj
        mrjj Lifetime Qt Champion @sachinrd last edited by

        @sachinrd
        That is really .. not so pretty :)
        can you try this ?

        void MainWindow::PrintWidget(QWidget* widget) {
        
          QPixmap pix(widget->size());
          QPainter painter(&pix);
          widget->render(&painter);
          painter.end();
          QPrinter printer(QPrinter::HighResolution);
          printer.setPageOrientation(QPageLayout::Orientation::Landscape);
          printer.setOutputFormat(QPrinter::PdfFormat);
          printer.setPaperSize(QPrinter::A4);
          printer.setOutputFileName("test.pdf"); // will be in build folder
        
          painter.begin(&printer);  
          double xscale = printer.pageRect().width() / double(pix.width());
          double yscale = printer.pageRect().height() / double(pix.height());
          double scale = qMin(xscale, yscale);
          painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
                            printer.paperRect().y() + printer.pageRect().height() / 2);
          painter.scale(scale, scale);
          painter.translate(-widget->width() / 2, -widget->height() / 2);
          painter.drawPixmap(0, 0, pix);
        
          painter.end();
        }
        

        PrintWidget(ui->tableView);

        and see if that looks better ?

        alt text

        S 1 Reply Last reply Reply Quote 4
        • VRonin
          VRonin last edited by VRonin

          Managing paging manually is painful, you can use QTextDocument to do it for you:

          QFileDialog dialog(this);
          dialog.setDefaultSuffix("pdf");
          const QString pdffileName = dialog.getSaveFileName(this, tr("Save File"), tr("doc.pdf"), tr("file(.pdf)"));
          if(pdffileName.isEmpty())
              return;
          QTextDocument doc;
          QTextCursor cursor(doc);
          const int rowC = indexPageModel->rowCount();
          const int colC = indexPageModel->columnCount();
          cursor.insertTable(rowC ,colC);
          for(int i=0;i<rowC ;++i){
              for(int j=0;j<colC ;++j){
                  cursor.insertText(indexPageModel->index(i,j).data().toString());
                  cursor.movePosition(QTextCursor::NextCell);
              }
          }
          QPrinter printer;
          printer.setOutputFileName(pdffileName);
          printer.setOutputFormat(QPrinter::PdfFormat);
          printer.setPageSize(QPageSize(QPageSize::A4));
          doc.print(&printer);
          

          P.S.
          I think you are leaking the model. change it to QStandardItemModel *indexPageModel=new QStandardItemModel(this);

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          S 1 Reply Last reply Reply Quote 3
          • JonB
            JonB @sachinrd last edited by JonB

            @sachinrd
            @VRonin's suggestion of going via QTextDocument is much easier/more robust. But be aware this will produce a table in PDF with the textual content from the model; it will not necessarily look like what you see in the QTableView (e.g. column widths, coloring, style, etc.). So long as that is acceptable to you.

            S 1 Reply Last reply Reply Quote 4
            • artwaw
              artwaw @sachinrd last edited by

              @sachinrd Hi,
              I'd also advise you to switch to QPdfWriter if your intention is to only write PDF files. Makes life easier.

              For more information please re-read.

              Kind Regards,
              Artur

              1 Reply Last reply Reply Quote 5
              • S
                sachinrd @VRonin last edited by sachinrd

                @VRonin said in Not able to render a tableview to pdf.:

                QFileDialog dialog(this);
                dialog.setDefaultSuffix("pdf");
                const QString pdffileName = dialog.getSaveFileName(this, tr("Save File"), tr("doc.pdf"), tr("file(.pdf)"));
                if(pdffileName.isEmpty())
                return;
                QTextDocument doc;
                QTextCursor cursor(doc);
                const int rowC = indexPageModel->rowCount();
                const int colC = indexPageModel->columnCount();
                cursor.insertTable(rowC ,colC);
                for(int i=0;i<rowC ;++i){
                for(int j=0;j<colC ;++j){
                cursor.insertText(indexPageModel->index(i,j).data().toString());
                cursor.movePosition(QTextCursor::NextCell);
                }
                }
                QPrinter printer;
                printer.setOutputFileName(pdffileName);
                printer.setOutputFormat(QPrinter::PdfFormat);
                printer.setPageSize(QPageSize(QPageSize::A4));
                doc.print(&printer);

                Thanks for the reply @VRonin . I tried this solution.. But i want to add a header and footer to the page.. Finding it tough to add it with this approach. And i also have one column with a checkbox widget. rendering that with this approach would be tough right..

                1 Reply Last reply Reply Quote 0
                • S
                  sachinrd @JonB last edited by

                  @JonB yes, i do want to render it as it looks in the QTableView. Is there an easy way to do this. I am able to render it to a pixmap and then paint it to printer object using a painter.
                  Something like this:
                  painter->drawPixmap(textRect,pix,QRect(0,0,pix.size().width(),pix.size().height()));
                  But The content is appearing a bit bigger . Screenshot 2021-05-31 at 5.20.10 PM.png

                  mrjj 1 Reply Last reply Reply Quote 0
                  • mrjj
                    mrjj Lifetime Qt Champion @sachinrd last edited by

                    @sachinrd
                    That is really .. not so pretty :)
                    can you try this ?

                    void MainWindow::PrintWidget(QWidget* widget) {
                    
                      QPixmap pix(widget->size());
                      QPainter painter(&pix);
                      widget->render(&painter);
                      painter.end();
                      QPrinter printer(QPrinter::HighResolution);
                      printer.setPageOrientation(QPageLayout::Orientation::Landscape);
                      printer.setOutputFormat(QPrinter::PdfFormat);
                      printer.setPaperSize(QPrinter::A4);
                      printer.setOutputFileName("test.pdf"); // will be in build folder
                    
                      painter.begin(&printer);  
                      double xscale = printer.pageRect().width() / double(pix.width());
                      double yscale = printer.pageRect().height() / double(pix.height());
                      double scale = qMin(xscale, yscale);
                      painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
                                        printer.paperRect().y() + printer.pageRect().height() / 2);
                      painter.scale(scale, scale);
                      painter.translate(-widget->width() / 2, -widget->height() / 2);
                      painter.drawPixmap(0, 0, pix);
                    
                      painter.end();
                    }
                    

                    PrintWidget(ui->tableView);

                    and see if that looks better ?

                    alt text

                    S 1 Reply Last reply Reply Quote 4
                    • S
                      sachinrd @mrjj last edited by

                      @mrjj said in Not able to render a tableview to pdf.:

                      PrintWidget(ui->tableView);

                      Thanks for the reply @mrjj . This is working perfect for me. Thanks a lot for the help !!

                      mrjj 1 Reply Last reply Reply Quote 1
                      • mrjj
                        mrjj Lifetime Qt Champion @sachinrd last edited by

                        @sachinrd
                        You are welcome.
                        Do notice this way of printing it only works when it
                        can fit on one page. if it has many rows, it will not be optimal :)

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post