3

I'm trying to take a screenshot using PySide (and return a QPixmap). This is part of a larger script. Unfortunately, I'm running into a wall at the moment.

Here's a simplified snippet that I'm trying to get to work:

from PySide2 import QtGui, QtWidgets

screen = QtWidgets.QApplication.primaryScreen()
winid = QtWidgets.QApplication.desktop().winId()
pixmap = screen.grabWindow(winid)

label = QtWidgets.QLabel("test")
label.setPixmap(pixmap)
label.show()

When executing this, it throws the following error:

TypeError: 'PySide2.QtGui.QScreen.grabWindow' called with wrong argument types:
PySide2.QtGui.QScreen.grabWindow(int)
Supported signatures:
PySide2.QtGui.QScreen.grabWindow(quintptr, int = 0, int = 0, int = -1, int = -1)

I'm using PySide version 2.0.0~alpha0 (which is the version that ships with the host application I'm using). I've tested the same code in a new version of the host application that uses PySide2 version 5.12.2, which executed as expected, without any errors... However, I'm limited to using the older version of the host application.

Does anyone know of a workaround?

First that came to mind was using PyQt5 to generate the QPixmap, and have PySide take it from there, but when testing this it turned out the PyQt QPixmap wasn't compatible with PySide. Porting the entire script to PyQt isnt an option either.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241

2 Answers2

5

If you can get the QPixmap with PyQt5 then you can convert that information to a generic data type as bytes that can be read by PySide2:

import sys

from PySide2 import QtCore, QtGui, QtWidgets


def take_screenshot():
    from PyQt5 import QtCore as pyqt5c
    from PyQt5 import QtWidgets as pyqt5w

    screen = pyqt5w.QApplication.primaryScreen()
    winid = pyqt5w.QApplication.desktop().winId()
    pixmap = screen.grabWindow(winid)

    ba = pyqt5c.QByteArray()
    buff = pyqt5c.QBuffer(ba)
    pixmap.save(buff, "PNG")
    return ba.data()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    data = take_screenshot()

    pixmap = QtGui.QPixmap()
    pixmap.loadFromData(data)

    label = QtWidgets.QLabel()
    label.setPixmap(pixmap)
    label.show()

    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
1

I'm a bit late on this, but faced similar issue while using QPixmap to save a screen shot. How I worked around it was converting the winId to a long int.

import maya.OpenMayaUI as _omui
from PySide2 import QtWidgets, QtGui
from shiboken2 import wrapInstance

def get_maya_main_window():
    win = _omui.MQtUtil_mainWindow()
    ptr = wrapInstance(long(win), QtWidgets.QMainWindow)
    return ptr

main_window_id = get_maya_main_window().winId()
long_win_id = long(main_window_id)

frame = QtGui.QPixmap.grabWindow(long_win_id)
path = <your-path-here>

frame.save(path)
Esteis
  • 4,669
  • 2
  • 29
  • 45
skids
  • 11
  • 2
  • 1
    I'm a bit late on this, but faced similar issue while using QPixmap to save a screen shot, How I worked around it was converting the winId to a long int. – skids May 03 '20 at 12:19
  • Welcome to stackoverflow and thanks for answering! Could you add an explanation of what you did to solve the problem to your answer? – Run_Script May 03 '20 at 13:48
  • Hi Skids, thanks for your answer, and the explanation in the comment. I've take the liberty of submitting an edit that moves your comment into the answer, because it's a good summary; if you agree, all you have to do is to accept the edit. I don't have a `long` function in my Python, and I can't find it in the docs. Do you know what the necessary `import` statement is, by any chance? Thanks again for your answer, and welcome to Stack Overflow! – Esteis May 03 '20 at 15:07
  • Hi Esteis, long is one of the default numeric types of python, so you would not need an import for that. In python what differentiates a long value from an int is 'L' at the end. You can initialize a long by just typing an integer value followed by L. for e.g. 98524 is an int data type, and 98524L is long. For this to work, try having the value being passed as long to the grab window function. It should definitely work and apologies for the late reply. – skids Jun 30 '20 at 06:48