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 predictable background before you start drawing anything.

You can use any color you like — #ffffff or Qt.GlobalColor.white for white, or any other 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.

PyQt/PySide Development Services — Stuck in development hell? I'll help you get your project focused, finished and released. Benefit from years of practical experience releasing software with Python.

Find out More

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.

PyQt6 Crash Course by Martin Fitzpatrick — The important parts of PyQt6 in bite-size chunks

See the course

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

Clearing the canvas in QPainter was written by Martin Fitzpatrick.

Martin Fitzpatrick is the creator of Python GUIs, and has been developing Python/Qt applications for the past 12+ years. He has written a number of popular Python books and provides Python software development & consulting for teams and startups.