Qt Forum

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

    [Solved] How to take a Print in QML?

    QML and Qt Quick
    3
    15
    16135
    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.
    • I
      IT MAN 2015 last edited by IT MAN 2015

      Hello ;
      I need to take a print in Qt Quick, So I Can't find any way to do this.
      Of course I checked this link : http://doc.qt.io/qt-5/qtprintsupport-index.html , but this work on widgets only not QML.

      So if anyone need to take print a page in QML how can do this ?
      for example I need take print from WebView content , TableView , Rectangle or other objects in QML.

      p3c0 1 Reply Last reply Reply Quote 0
      • p3c0
        p3c0 Moderators @IT MAN 2015 last edited by

        Hi @IT-MAN-2015,
        QML doesnot have any such mechanism of printing. You will need to make use of Qt's C++ API's for actual printing. First you can grab image of any Item using grabToImage the result will be delegated to a callback. Inside it you can get the grabbed image data which is actually a QImage. Later you can send it to C++ side using signal/slot or by calling a Q_INVOKABLE function. Then use QPrinter to print that image.

        157

        I 1 Reply Last reply Reply Quote 1
        • I
          IT MAN 2015 @p3c0 last edited by IT MAN 2015

          @p3c0 said:

          Hi @IT-MAN-2015,
          QML doesnot have any such mechanism of printing. You will need to make use of Qt's C++ API's for actual printing. First you can grab image of any Item using grabToImage the result will be delegated to a callback. Inside it you can get the grabbed image data which is actually a QImage. Later you can send it to C++ side using signal/slot or by calling a Q_INVOKABLE function. Then use QPrinter to print that image.

          Well , for example I wrote this codes for webView but I can't get webView source for send to C++ function to print it.

          C++ Invokable function
          .h file

          #ifndef PR_H
          #define PR_H
          
          #include <QObject>
          
          
          class pr : public QObject
          {
              Q_OBJECT
          
          public:
              pr();
          
          public:
          
          Q_INVOKABLE  void print(QString url);
          
          
          };
          
          #endif // PR_H
          

          .cpp :

          void pr::print(QString url)
          
          {
          
              QString fileName = QFileDialog::getOpenFileName(0,"Open File",QString(),"PNG File(*.png)");
              QPrinter printer;
                    QPrintDialog *dlg = new QPrintDialog(&printer,0);
                    if(dlg->exec() == QDialog::Accepted) {
                            QImage img(fileName);
                            QPainter painter(&printer);
                            painter.drawImage(QPoint(0,0),img);
                            painter.end();
                    }
          
          
          }
          

          main file :

          //For QML
          pr  print;
          
              engine.rootContext()->setContextProperty("PRINT", &print);
          

          QMl file :

                      WebView {
                          id: result_view
                          x: 154
                          y: 22
                          url:"https://forum.qt.io/logo.png"
          
                      }
          
                  Button {
                      id: button1
                      x: 437
                      y: 137
                      width: 150
                      height: 36
                      text: qsTr("Print")
                      onClicked: {
                          PRINT.print(/*My WebView Content*/);
                      }
                  }
          
          p3c0 1 Reply Last reply Reply Quote 0
          • p3c0
            p3c0 Moderators @IT MAN 2015 last edited by

            @IT-MAN-2015 As said earlier use grabToImage to grab a snapshot of the Item i.e in your case WebView. Then its result will give you QImage and then send it to C++. So instead of (QString url) as argument use QVariant and convert it to QImage. Following should work as per your code:

            WebView {
                id: webview
                anchors.fill: parent
                url: "https://forum.qt.io/logo.png"
            }
            
            Button {
                anchors.bottom: parent.bottom
                onClicked: {
                    var stat = result_view.grabToImage(function(result) {
                        //result.saveToFile("/home/user/someimage.png"); //saves to a file
                        PRINT.print(result.image); //result.image holds the QVariant
                    });
                    console.log("Success: ", stat);
                }
            }
            

            157

            I 1 Reply Last reply Reply Quote 1
            • I
              IT MAN 2015 @p3c0 last edited by p3c0

              @p3c0 said:

              @IT-MAN-2015 As said earlier use grabToImage to grab a snapshot of the Item i.e in your case WebView. Then its result will give you QImage and then send it to C++. So instead of (QString url) as argument use QVariant and convert it to QImage. Following should work as per your code:

              WebView {
                  id: webview
                  anchors.fill: parent
                  url: "https://forum.qt.io/logo.png"
              }
              
              Button {
                  anchors.bottom: parent.bottom
                  onClicked: {
                      var stat = result_view.grabToImage(function(result) {
                          //result.saveToFile("/home/user/someimage.png"); //saves to a file
                          PRINT.print(result.image); //result.image holds the QVariant
                      });
                      console.log("Success: ", stat);
                  }
              }
              

              Thank you p3c0 for your helping.
              But I can't convert QVariant to QImage
              I think my function is wrong! QPrintDialog not work when I write custom path.

              void pr::print(QVariant *url)
              
              {
                  //QString fileName = QFileDialog::getOpenFileName(0,"Open File",QString(),"PNG File(*.png)");
                  QPrinter printer;
                        QPrintDialog *dlg = new QPrintDialog(&printer,0);
                        if(dlg->exec() == QDialog::Accepted) {
                           
                                //Convert my QVariant to image file
                                url->toImage ?!!? how convert to image :(
                            
                                QImage img(fileName);
                                QPainter painter(&printer);
                                painter.drawImage(QPoint(0,0),img);
                                painter.end();
                        }
              }
              
              p3c0 1 Reply Last reply Reply Quote 0
              • p3c0
                p3c0 Moderators @IT MAN 2015 last edited by

                @IT-MAN-2015 Not need of QVariant pointer. It is implicily shared. Afterwards use qvariant_cast to cast it to QImage and then as usual of printing. So

                void pr::print(QVariant data) { //note: it sends a complete image and not just url
                     QImage img = qvariant_cast<QImage>(data);
                }
                

                157

                I 1 Reply Last reply Reply Quote 1
                • I
                  IT MAN 2015 @p3c0 last edited by p3c0

                  @p3c0 said:

                  @IT-MAN-2015 Not need of QVariant pointer. It is implicily shared. Afterwards use qvariant_cast to cast it to QImage and then as usual of printing. So

                  void pr::print(QVariant data) { //note: it sends a complete image and not just url
                       QImage img = qvariant_cast<QImage>(data);
                  }
                  

                  Well... I understand about QVariant but now i get error !

                  error: C2664: 'void pr::print(QVariant)' : cannot convert argument 1 from 'QVariant' to 'QVariant'
                  Source or target has incomplete type

                  .h file :

                  #ifndef PR_H
                  #define PR_H
                  #include <QObject>
                  class pr : public QObject
                  {
                      Q_OBJECT
                  public:
                      pr();
                  public:
                  Q_INVOKABLE void print(QVariant data);
                  };
                  #endif // PR_H
                  

                  and .cpp file :

                  pr::pr()
                  {
                  }
                  void pr::print(QVariant data)
                  {
                     QImage img = qvariant_cast<QImage>(data);
                     QPrinter printer;
                            QPrintDialog *dlg = new QPrintDialog(&printer,0);
                            if(dlg->exec() == QDialog::Accepted) {
                                    QPainter painter(&printer);
                                    painter.drawImage(QPoint(0,0),img);
                                    painter.end();
                            }
                  }
                  
                  p3c0 1 Reply Last reply Reply Quote 0
                  • T
                    timday last edited by

                    It's worth mentioning this is one of the few things the old Qt4.8-era QDeclarativeView could do better, due to being QPainter based instead of OpenGL; see http://stackoverflow.com/questions/20825233/how-to-print-a-qquickviews-contents-to-pdf . (Well in theory; in practice the PDFs seemed to have some flaws.)

                    The possibility of using the new (commerical license) QtQuick software rendering tech for improving print capabilities gets a brief mention in the thread under https://blog.qt.io/blog/2015/01/22/introducing-the-qt-quick-2d-renderer/ too.

                    p3c0 1 Reply Last reply Reply Quote 0
                    • p3c0
                      p3c0 Moderators @IT MAN 2015 last edited by

                      @IT-MAN-2015 do #include <QVariant>

                      157

                      I 1 Reply Last reply Reply Quote 1
                      • I
                        IT MAN 2015 @p3c0 last edited by

                        @p3c0

                        Thank you p30c0 :-) I understand and I can take a print in QML right now.
                        Thank you for your helping my friend.

                        p3c0 1 Reply Last reply Reply Quote 0
                        • p3c0
                          p3c0 Moderators @IT MAN 2015 last edited by

                          @IT-MAN-2015 You're Welcome :) Also please surround you code with ``` (3 backticks) while posting here so that it gets formatted nicely and is more readable.

                          157

                          I 1 Reply Last reply Reply Quote 2
                          • p3c0
                            p3c0 Moderators @timday last edited by

                            @timday

                            It's worth mentioning this is one of the few things the old Qt4.8-era QDeclarativeView could do better, due to being QPainter based instead of OpenGL; see http://stackoverflow.com/questions/20825233/how-to-print-a-qquickviews-contents-to-pdf . (Well in theory; in practice the PDFs seemed to have some flaws.)

                            Yes indeed. Miss them for these features including WebView. I guess in future we may have a direct print function in QtQuick 2.x too.

                            157

                            1 Reply Last reply Reply Quote 1
                            • I
                              IT MAN 2015 @p3c0 last edited by IT MAN 2015

                              @p3c0 said:

                              @IT-MAN-2015 You're Welcome :) Also please surround you code with ``` (3 backticks) while posting here so that it gets formatted nicely and is more readable.

                              Here you are :

                              .h file

                              #ifndef PR_H
                              #define PR_H
                              
                              #include <QObject>
                              #include <QVariant>
                              
                              class pr : public QObject
                              {
                                  Q_OBJECT
                              
                              public:
                                  pr();
                              
                              public:
                              
                              Q_INVOKABLE void print(QVariant data);
                              
                              
                              };
                              
                              #endif // PR_H
                              

                              .cpp file :

                              #include "pr.h"
                              #include <QPrinter>
                              #include <QPainter>
                              #include <QPrintDialog>
                              #include <QPixmap>
                              #include <QImage>
                              #include <qDebug>
                              
                              pr::pr()
                              {
                              
                              }
                              
                              void pr::print(QVariant data)
                              
                              {
                              
                              
                                  QImage img = qvariant_cast<QImage>(data);
                                  QPrinter printer;
                                        QPrintDialog *dlg = new QPrintDialog(&printer,0);
                                        if(dlg->exec() == QDialog::Accepted) {
                                                QPainter painter(&printer);
                                                painter.drawImage(QPoint(0,0),img);
                                                painter.end();
                                        }
                              
                              
                              }
                              
                              

                              QML file :

                                          WebView {
                                              id: result_view
                                              x: 154
                                              y: 22
                                              url:"http://forum.qt.io/logo.png"
                                              enabled: false
                                              antialiasing: true
                              
                                          }
                              
                              
                                      Button {
                                          id: button1
                                          x: 437
                                          y: 137
                                          width: 150
                                          height: 36
                                          text: qsTr("Print")
                                          onClicked: {
                                                  var stat = result_view.grabToImage(function(result) {
                                                      //result.saveToFile("/home/user/someimage.png"); //saves to a file
                                                      PRINT.print(result.image); //result.image holds the QVariant
                                                  });
                                                  console.log("Success: ", stat);
                                              }
                                      }
                              
                              

                              main.cpp

                              #include <QApplication>
                              #include <QQmlApplicationEngine>
                              #include <QtWebEngine/QtWebEngine>
                              #include <pr.h>
                              
                              int main(int argc, char *argv[])
                              {
                                  QApplication app(argc, argv);
                              
                                  QQmlApplicationEngine engine;
                                  QtWebEngine::initialize();
                              
                                  //For QML
                                  pr  print;
                                  engine.rootContext()->setContextProperty("PRINT", &print);
                                  engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                              
                                  return app.exec();
                              }
                              
                              p3c0 1 Reply Last reply Reply Quote 4
                              • p3c0
                                p3c0 Moderators @IT MAN 2015 last edited by

                                @IT-MAN-2015 Thanks for sharing :)

                                157

                                I 1 Reply Last reply Reply Quote 1
                                • I
                                  IT MAN 2015 @p3c0 last edited by

                                  @p3c0 said:

                                  @IT-MAN-2015 Thanks for sharing :)

                                  You're welcome :)
                                  Have a nice time.

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