Screenshot capture of dual monitor in Qt 5
Asked Answered
J

3

5

In the context of a Qt application, I'm using the following code snippet for taking a screenshot of the full desktop:

QDesktopWidget* dw = QApplication::desktop();
QPixmap pixmap = QPixmap::grabWindow(dw->winId(), 0, 0,
                                     dw->width(), dw->height());
pixmap.save(name, "JPG", screenshot_quality);

This approach works pretty well in Linux and Windows and with dual monitor, independently of screen's resolutions; that is, it works still if the two monitors are working with different resolutions.

However, with Qt 5, I get the following run-time warning:

static QPixmap QPixmap::grabWindow(WId, int, int, int, int) is deprecated, use QScreen::grabWindow() instead. Defaulting to primary screen.

So I reviewed the Qt 5 doc and I wrote this:

QScreen * screen = QGuiApplication::primaryScreen();
QPixmap pixmap = screen->grabWindow(0);
pixmap.save(name, "JPG", screenshot_quality);

But this approach does not capture the second screen.

So I searched a little more and, according to this thread, Taking Screenshot of Full Desktop with Qt5, I designed the screenshot capture as follows:

QScreen * screen = QGuiApplication::primaryScreen();
QRect g = screen->geometry();
QPixmap pixmap = screen->grabWindow(0, g.x(), g.y(), g.width(), g.height());
pixmap.save(name, "JPG", screenshot_quality);

Unfortunately, this does not work either.

What catches my attention is that the method with Qt 4 works well. Since I imagine there must be some way to make it in Qt 5.

How can be done with Qt 5?

Johanajohanan answered 21/4, 2016 at 15:55 Comment(1)
I've edited out the answer as it does not belong in the question, but in an answer box. If you wish to share it, please add it as an answer, otherwise I will be adding it as a community wiki. See How to treat an old question which had an answer edited into it?Pleven
C
5

Naturally, QGuiApplication::primaryScreen() will give you a single screen.

You could:

  • Use QList<QScreen *> QGuiApplication::screens() to get all screens associated with the application.
  • Take screenshots for all of them.
  • Create another blank image.
  • Size it according to how you want to compose the screens.
  • Manually compose them into a final image using QPainter.
QPixmap grabScreens() {
  auto screens = QGuiApplication::screens();
  QList<QPixmap> scrs;
  int w = 0, h = 0, p = 0;
  foreach (auto scr, screens) {
    QPixmap pix = scr->grabWindow(0);
    w += pix.width();
    if (h < pix.height()) h = pix.height();
    scrs << pix;
  }
  QPixmap final(w, h);
  QPainter painter(&final);
  final.fill(Qt::black);
  foreach (auto scr, scrs) {
    painter.drawPixmap(QPoint(p, 0), scr);
    p += scr.width();
  }
  return final;
}
Conspecific answered 21/4, 2016 at 16:5 Comment(0)
Y
3

For old Qt versions:

You can use primary screen's (desktop) virtual geometry and capture entire desktop without additional loops and calculations:

QRect desktopGeometry = qApp->primaryScreen()->virtualGeometry();
QPixmap desktopPixmap = qApp->primaryScreen()->grabWindow(qApp->desktop()->winId(), desktopGeometry.x(), desktopGeometry.y(), desktopGeometry.width(), desktopGeometry.height());

See also: QDesktopWidget


For new Qt versions:

QApplication::desktop() and QDesktopWidget are marked as obsolete, so for new projects it's recommended to use approach with screen enumerating.

Yeomanly answered 25/7, 2018 at 12:10 Comment(0)
P
0

Answer provided by lrleon:

Based on this answer, I came up with this:

QPixmap grabScreens()
{
  QList<QScreen*> screens = QGuiApplication::screens();
  QList<QPixmap> scrs;
  int w = 0, h = 0, p = 0;

  foreach (auto scr, screens)
    {
      QRect g = scr->geometry();
      QPixmap pix = scr->grabWindow(0, g.x(), g.y(), g.width(), g.height());
      w += pix.width();
      h = max(h, pix.height());
      scrs.append(pix);
    }

  QPixmap final(w, h);
  QPainter painter(&final);
  final.fill(Qt::black);
  foreach (auto scr, scrs)
    {
      painter.drawPixmap(QPoint(p, 0), scr);
      p += scr.width();
    }

  return final;
}
Pleven answered 21/4, 2016 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.