Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QOpenGLWidget does not render to printer



  • How to render a QOpenGLWidget to printer, that renders correctly onto a screen, but fails for a printer?
    The documentation of Qwidget::render tells:
    Note: To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer() instead.
    Note: To obtain the contents of a QGLWidget (deprecated), use QGLWidget::grabFrameBuffer() or QGLWidget::renderPixmap() instead.

    Nevertheless QGLWidget::render works seamlessly, and only QOpenGLWidget::render does not work yielding a blank widget. grabFramebuffer first of all is incredible slow and the result is very strange, items in the OpenGL graph change their scale and position compared to the screen output.

    For example adding print [0_1537963600518_testOpenGl.pdf](Uploading 100%) support to the 2painting example (see following code) gives
    [0_1537963045949_testOpenGl.pdf](Uploading 100%)

    Using the 2Dpainting example with the following changes:
    2dpainting.pro (add printsupport and opengl)

    QT          += widgets printsupport opengl
    
    
    HEADERS     = \
                  helper.h \
                  widget.h \
                  window.h \
                  openglwidget.h \
                  glwidget.h
    SOURCES     = \
                  helper.cpp \
                  main.cpp \
                  widget.cpp \
                  window.cpp \
                  openglwidget.cpp \
                  glwidget.cpp
    
    # install
    target.path = $$[QT_INSTALL_EXAMPLES]/opengl/2dpainting
    INSTALLS += target
    

    openglwidget.h, .cpp just renamed glWidget (change of class name)

    //! [0]
    class Helper;
    
    class OpenGLWidget: public QOpenGLWidget
    {
        Q_OBJECT
    ...
    

    glwidget.h (just some changes, derive from GLWidget instead of QOpenGLWidget)

    //! [0]
    class Helper;
    
    class GLWidget: public QGLWidget
    {
        Q_OBJECT
    
    

    glwidget.cpp

    //! [0]
    GLWidget::GLWidget(Helper *helper, QWidget *parent)
        : QGLWidget(parent), helper(helper)
    {
        elapsed = 0;
    

    and finally window.h as well as

    class Window : public QWidget
    {
        Q_OBJECT
    
    public:
        Window();
    private:
        void openPrintDialog();
    
        void print(QPrinter *printer);
    
    private:
        Helper helper;
    };
    

    and window.cpp adding the new widget and the label as well as the print button.

    //! [0]
    Window::Window()
    {
        setWindowTitle(tr("2D Painting on Native and OpenGL Widgets"));
    
        Widget *native = new Widget(&helper, this);
        OpenGLWidget *openGL = new OpenGLWidget(&helper, this);
        GLWidget *gL = new GLWidget(&helper, this);
        QLabel *nativeLabel = new QLabel(tr("Native"));
        nativeLabel->setAlignment(Qt::AlignHCenter);
        QLabel *gLLabel = new QLabel(tr("QGLWidget"));
        gLLabel->setAlignment(Qt::AlignHCenter);
        QLabel *openGLLabel = new QLabel(tr("QOpenGLWidget"));
        openGLLabel->setAlignment(Qt::AlignHCenter);
        QPushButton *pushButton = new QPushButton("Print", this);
        connect(pushButton, &QPushButton::clicked, this, &Window::openPrintDialog);
    
        QGridLayout *layout = new QGridLayout;
        layout->addWidget(native, 0, 0);
        layout->addWidget(openGL, 0, 1);
        layout->addWidget(gL, 0, 2);
        layout->addWidget(nativeLabel, 1, 0);
        layout->addWidget(openGLLabel, 1, 1);
        layout->addWidget(gLLabel, 1, 2);
        layout->addWidget(pushButton, 2, 1);
        setLayout(layout);
    
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, native, &Widget::animate);
        connect(timer, &QTimer::timeout, openGL, &OpenGLWidget::animate);
        connect(timer, &QTimer::timeout, gL, &GLWidget::animate);
        timer->start(50);
    }
    
    void Window::openPrintDialog() {
        QPrinter printer(QPrinter::PrinterResolution);
        QPrintDialog dialog(&printer, this);
    
        dialog.setWindowTitle("Print Graphics");
    
        switch (dialog.exec()) {
        case QDialog::Accepted:
            print(&printer);
            break;
        default:
            break;
        }
    
    }
    
    void Window::print(QPrinter *printer) {
        QPainter painter;
        painter.begin(printer);
    
        double  xScale = printer->pageRect().width() / double(width());
        double  yScale = printer->pageRect().height()/ double(height());
    
        double scale = qMin(xScale, yScale);
    
        painter.translate(
             printer->paperRect().x() + printer->paperRect().width() /2,
             printer->paperRect().y() + printer->paperRect().height()/2
        );
        painter.scale(scale, scale);
    
        render(&painter, QPoint(-width()/2, -height()/2));
    
    }
    

  • Lifetime Qt Champion

    Hi,

    You should add the Qt version you are using as well as the OS you are running.

    Did you already check the bug report system to see if there's anything related ?



  • The issue occurs tested with QT version 5.4 (under Win7) and the latest one 5.11.2 (under Win 10). I guess it will be the same for all versions inbetween. When nothing is mentioned you should allways take into account the latest stable release. The issue seams to be related with the fact, that QPainter is doing the job and not a real paintGL() function with OpenGL code is being called. By the way the "Hello GL2 Example" can be tweaked similar to what I did in the 2dpainting example and prints correctly.

    There are some issues concerning rendering QOpenGLWidget reported in the bug tracker, but according to my understanding nothing related.

    I even can't tell, that it is a real bug, as the 2dpainting example should just show some animated graph, nevertheless it is not of much use to demonstrate the use of OpenGL inside QT.

    Sorry for the late answer, but it looks as if I did not receive any notification.


Log in to reply