Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Not able to render a tableview to pdf.
Forum Updated to NodeBB v4.3 + New Features

Not able to render a tableview to pdf.

Scheduled Pinned Locked Moved Solved General and Desktop
qprinterpainterrenderingqt desktop
9 Posts 5 Posters 1.4k Views 3 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.
  • S Offline
    S Offline
    sachinrd
    wrote on 31 May 2021, 08:05 last edited by sachinrd
    #1

    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()));```
    J A 2 Replies Last reply 31 May 2021, 10:45
    0
    • S sachinrd
      31 May 2021, 11:59

      @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

      M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 31 May 2021, 15:23 last edited by
      #7

      @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 31 May 2021, 15:55
      4
      • V Offline
        V Offline
        VRonin
        wrote on 31 May 2021, 10:05 last edited by VRonin
        #2

        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 31 May 2021, 11:45
        3
        • S sachinrd
          31 May 2021, 08:05

          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()));```
          J Offline
          J Offline
          JonB
          wrote on 31 May 2021, 10:45 last edited by JonB
          #3

          @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 31 May 2021, 11:59
          4
          • S sachinrd
            31 May 2021, 08:05

            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()));```
            A Offline
            A Offline
            artwaw
            wrote on 31 May 2021, 10:47 last edited by
            #4

            @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
            5
            • V VRonin
              31 May 2021, 10:05

              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);

              S Offline
              S Offline
              sachinrd
              wrote on 31 May 2021, 11:45 last edited by sachinrd
              #5

              @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
              0
              • J JonB
                31 May 2021, 10:45

                @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 Offline
                S Offline
                sachinrd
                wrote on 31 May 2021, 11:59 last edited by
                #6

                @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

                M 1 Reply Last reply 31 May 2021, 15:23
                0
                • S sachinrd
                  31 May 2021, 11:59

                  @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

                  M Offline
                  M Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on 31 May 2021, 15:23 last edited by
                  #7

                  @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 31 May 2021, 15:55
                  4
                  • M mrjj
                    31 May 2021, 15:23

                    @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 Offline
                    S Offline
                    sachinrd
                    wrote on 31 May 2021, 15:55 last edited by
                    #8

                    @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 !!

                    M 1 Reply Last reply 31 May 2021, 16:02
                    1
                    • S sachinrd
                      31 May 2021, 15:55

                      @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 !!

                      M Offline
                      M Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on 31 May 2021, 16:02 last edited by
                      #9

                      @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
                      0

                      1/9

                      31 May 2021, 08:05

                      • Login

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