Clearing the canvas in QPainter

Fix the common black background issue when painting on a QPixmap in PyQt6
Heads up! You've already completed this tutorial.

My canvas is not clearing every time I run my painting app, and on Windows the background appears black instead of white. How do I properly clear or fill the canvas when using QPainter and QPixmap in PyQt6?

If you've been following along with QPainter tutorials and find that your canvas has a black background — or that previous drawings aren't being cleared properly — you're running into one of the most common gotchas when working with QPixmap in PyQt6, especially on Windows.

The good news is that the fix is simple: you just need to explicitly fill your QPixmap with a color when you create it.

Why does the canvas appear black?

When you create a new QPixmap, the pixel data it contains is uninitialized. On some platforms (particularly Windows), this uninitialized data shows up as solid black. On other platforms, you might see random garbage pixels or a transparent background. The behavior is unpredictable because you're looking at whatever happened to be in that block of memory.

The solution is to fill the pixmap with your desired background color right after creating it.

Filling the canvas with a background color

Here's how to create a QPixmap and fill it with white:

python
from PyQt6 import QtGui

canvas = QtGui.QPixmap(400, 300)
canvas.fill(QtGui.QColor("#ffffff"))  # Fill entire canvas with white.

The fill() method sets every pixel in the pixmap to the color you specify. By calling it immediately after creating the pixmap, you ensure a clean, predictable background before you start drawing anything.

You can use any color you like — #ffffff for white, Qt.GlobalColor.white, or any QColor value.

A complete working example

Here's a full example that creates a small painting application. The canvas starts with a white background, and you can click buttons to draw shapes on it. Notice how canvas.fill() is called right after the QPixmap is created.

python
import sys

from PyQt6 import QtCore, QtGui, QtWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        self.canvas = QtGui.QPixmap(400, 300)
        self.canvas.fill(QtGui.QColor("#ffffff"))  # Start with a white canvas.

        self.label = QtWidgets.QLabel()
        self.label.setPixmap(self.canvas)

        button_draw = QtWidgets.QPushButton("Draw Rectangle")
        button_draw.clicked.connect(self.draw_rectangle)

        button_clear = QtWidgets.QPushButton("Clear Canvas")
        button_clear.clicked.connect(self.clear_canvas)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(button_draw)
        layout.addWidget(button_clear)

        container = QtWidgets.QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

    def draw_rectangle(self):
        painter = QtGui.QPainter(self.canvas)
        pen = QtGui.QPen()
        pen.setWidth(3)
        pen.setColor(QtGui.QColor("#333333"))
        painter.setPen(pen)
        painter.drawRect(50, 50, 200, 150)
        painter.end()
        self.label.setPixmap(self.canvas)

    def clear_canvas(self):
        self.canvas.fill(QtGui.QColor("#ffffff"))  # Reset to white.
        self.label.setPixmap(self.canvas)


app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

Copy and run this to see it in action. Click "Draw Rectangle" to paint a shape, then click "Clear Canvas" to reset everything back to white. If you're new to building PyQt6 applications, see creating your first window for a beginner-friendly introduction.

How clearing works

The clear_canvas method does the same thing we did during initialization — it calls self.canvas.fill() to overwrite every pixel with white, then updates the QLabel by calling setPixmap() again. That's all there is to it. You don't need to call self.update() or any other manual refresh method when you're displaying your pixmap through a QLabel, because setPixmap() already triggers a repaint of the label widget.

When do you need self.update()?

If you're painting directly in a widget's paintEvent method (rather than painting onto a QPixmap displayed in a QLabel), then you would need to call self.update() to schedule a repaint after changing your drawing data. This approach is common when creating your own custom widgets. But when you're working with a QPixmap and a QLabel as shown above, calling setPixmap() handles the display update for you.

Summary

Whenever you create a QPixmap to use as a drawing canvas:

  1. Call canvas.fill() immediately after creation to set a known background color.
  2. To clear the canvas later, call canvas.fill() again with your background color.
  3. After modifying the pixmap, call label.setPixmap(canvas) to update the display.

This approach works reliably across all platforms and avoids the black background issue entirely. For more advanced drawing techniques, including working with QPainter paths and shapes, check out the QPainter and bitmap graphics tutorial.

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

Create GUI Applications with Python & Qt6 by Martin Fitzpatrick

(PyQt6 Edition) The hands-on guide to making apps with Python — Over 15,000 copies sold!

More info Get the book

Martin Fitzpatrick

Clearing the canvas in QPainter was written by Martin Fitzpatrick.

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt. Martin founded PythonGUIs to provide easy to follow GUI programming tutorials to the Python community. He has written a number of popular Python books on the subject.