0

I have a Qt program to visualize my data as a voxel grid (see picture below). However I just want to run the Qt program once, such that the data gets displayed, take a screenshot then exit the entire program.

Here is my code:

int main(int argc, char** argv) {
    QApplication app(argc, argv);
    Mainframe frame(voxelGrid);
    frame.show();
    app.exec();
    frame.saveScreenshot();
  return 0;
}

In the above example Mainframe is a class inheriting from QMainWindow.

However it seems that I need to call app.exec or else the saveScreenshot function will only store a black image. app.exec however results in an infinite loop and I need to manually close the window before the program continues with the screenshot saving. Any idea how to fix this?

Here is the data that I'm plotting: enter image description here

using Qt's screenshot function:

  QImage img = ui.mViewport->grabFrameBuffer();
  img.save("screenshot.png");
  QApplication::clipboard()->setImage(img);

where mViewport is a class inheriting from QGLWidget.
The entire Qt-Window looks like this: enter image description here

mcExchange
  • 6,154
  • 12
  • 57
  • 103
  • Yes, but I don't want to do it manually. I would need to run the quit command after 1 iteration of the `app.exec` loop. Alternatively I would need a command to display the window without entering the `app.exec` loop – mcExchange Aug 09 '18 at 09:48
  • Suggest adding `QGLWidget` or `opengl` tag. – JustWe Aug 10 '18 at 01:52

2 Answers2

0

I used Qt grabber example to take the screenshot:

#include "glwidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    GLWidget w;
    w.renderPixmap(w.width(), w.height()).save("screenshot.png");

    return 0;
}

enter image description here

Just use QGLWidget::renderPixmap to render the frame.

Internally the function renders into a framebuffer object and performs pixel readback.

JustWe
  • 4,250
  • 3
  • 39
  • 90
  • Could you please explain your answer? What is `QMainWindow`, `QPixmap` and `qDebug` for? What headers do I need to include in order to use them? – mcExchange Aug 09 '18 at 09:46
  • @mcExchange Sorry I am trying edit the answer, because I find you are using `grabFrameBuffer`. What's `mViewport` – JustWe Aug 09 '18 at 09:48
  • ah sorry, `mViewport` is a class inheriting from `QGLWidget` – mcExchange Aug 09 '18 at 09:50
  • Ok, with your example, the image is at least not black anymore, however, I only see the Qt-window with the menu bar now, but not whats inside the QGLWidget (mViewport) which is where my data is being displayed – mcExchange Aug 09 '18 at 09:56
0

So the solution looks like this:

int main(int argc, char** argv) {
  QApplication app(argc, argv);
  Mainframe frame(voxelGrid);
  frame.show();

  Viewport* widget;
  widget = frame.ui.mViewport;
  widget->show();

  QApplication::processEvents();
  QApplication::processEvents();

  widget->updateGL();
  frame.saveScreenshot();

  return 0;
}

So apparantly I had to get the pointer to the mViewport (QGLWidget) and then call QApplication::processEvents(); for 2 times (!) (one time is not enough for whatever reason). Finally the drawing method that was custom to the mViewport widget->updateGL(); then the frame.saveScreenshot(); worked.

Not sure if my problem was due to Qt or the specifics of the mViewport object. In the latter case my problem is probably of little help to others. Sorry ;)

Caveat: This method is unstable and the output image sizes vary or the ouput can be black from time to time. (I ended up visualizing the scenes using a Blender script)

mcExchange
  • 6,154
  • 12
  • 57
  • 103