Saturday, July 4, 2009

Qt-Embedded: Capturing screen with QPixmap

I've been working on a product manual lately. I needed to include several LCD screenshots into it so I tried to come up with an easy way to capture snapshots from our Qt/Embedded app.
Qt/Embedded provides a nice method to save window/framebuffer contents directly to an image file. However, I wanted to send the 'take-snapshot' command from a tty console (telnet/serial/etc) since there weren't any other buttons on the system to trigger that.
A QTimer is set up. Periodically it checks the file /tmp/doCapture. If it exists a snapshot is taken and an image file is saved. Its filename is taken from the contents of /tmp/doCapture. After saving the image /tmp/doCapture is deleted.
Here is the code, which should be placed in the main window, whose width and height cover the whole screen:

// captureTimer should be declared in mainWindow's class definition
captureTimer = new QTimer(this);
connect( captureTimer, SIGNAL(timeout()), this, SLOT(captureTimerEvent()) );

captureTimer->start(1000); //check interval

void mainWindow::captureTimerEvent()
QString tmpFile = QString("/tmp/doCapture");

if ( !QFile::exists(tmpFile) )

QFile f(tmpFile);
if ( ! QIODevice::ReadWrite ) )

char buf[200];
if ( f.readLine( buf, sizeof(buf) - 4 ) == -1 )

buf[strlen(buf)-1] = '\0'; //remove \n created by 'echo'-- not safe!

strcat( buf, ".png" );

QPixmap p = QPixmap::grabWindow( this->winId() );

if ( buf ) )
printf("------- GRAB OK\n");
printf("------- ERR GRAB!\n");

/* delete file */

This way, all I have to do to take a snapshot is to write:

echo pngfilename > /tmp/doCapture