Sunday, 21 March 2021

QWidget rendering to QPixmap ignores the background

I have written a QQuickPaintedItem to use the RichJupyterWidget in a QtQuick application. Everything works great except that when I draw the widget in the 'QQuickPaintedItem::paint' method, the background is white instead of black. It has nothing to do with QtQuick, the problem is that when I render to a QPixmap, the background is ignored.

I have tried a number of solutions without any luck. The following simple QWidget example demonstrates the issue. I am using Qt 5.15.2 and Python 3.8.6 (PySide2 and qtconsole). I have now tried Qt 5.12 and Python 3.7 on Windows and I see the same issue.

For anyone interested, the Python interpreter for QtQuick can be found here. https://github.com/JensMunkHansen/QtQuickIPython

Small reproducible example. The background in the saved image is supposed to be black...

from qtpy import QtWidgets
from qtconsole.rich_jupyter_widget import RichJupyterWidget
from qtconsole.inprocess import QtInProcessKernelManager

from qtpy.QtGui import QPixmap, QRegion, QPainter
from qtpy.QtCore import QFile, QIODevice, QRect, QPoint, QTimer, Qt


def show():
    global ipython_widget  # Prevent from being garbage collected

    # Create an in-process kernel
    kernel_manager = QtInProcessKernelManager()
    kernel_manager.start_kernel(show_banner=False)
    kernel = kernel_manager.kernel

    kernel_client = kernel_manager.client()
    kernel_client.start_channels()

    ipython_widget = RichJupyterWidget()
    
    ipython_widget.kernel_manager = kernel_manager
    ipython_widget.kernel_client = kernel_client
    ipython_widget.show()
    ipython_widget.set_default_style('linux') # Background is now black
    # First attempt - solution that I found on SO (no effect)
    ipython_widget.setAttribute(Qt.WA_StyledBackground, True)

    # My attempt, also no effect.
    p = ipython_widget.palette()
    p.setColor(ipython_widget.backgroundRole(), Qt.black)
    ipython_widget.setPalette(p)
    
def screenShot():
    print('saving')
    rect = QRect(0, 0, int(ipython_widget.width()),
                 int(ipython_widget.height()))
    picture = QPixmap(rect.size())
    ipython_widget.render(picture, QPoint(), QRegion(rect))

    painter = QPainter()
    file = QFile("./output.png")
    file.open(QIODevice.WriteOnly)
    picture.save(file, "PNG");
    painter.drawPixmap(QPoint(0,0), picture)
    

if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    show()
    
    timer = QTimer()
    timer.timeout.connect(lambda: screenShot())
    timer.start(5000)
    
    app.exec_()

This is not part of my integration of `RichJupyterWidget' for QtQuick, but a small solution demonstrating the same problem



from QWidget rendering to QPixmap ignores the background

No comments:

Post a Comment