How can I change the text color from black to white of the percentage indicator inside the
QProgressBarwhen it exceeds the value of 50?
When a QProgressBar fills past the halfway mark, the dark-colored chunk behind the text can make the default black percentage label hard to read. A common solution is to switch the text color to white once the value crosses 50%. Let's walk through how to do this in PyQt5 using stylesheets and a signal connection.
Why the text becomes hard to read
By default, QProgressBar draws its percentage text on top of the bar. When the colored "chunk" is small, the text sits against a light background and black text is fine. As the chunk grows and fills most of the bar, the text ends up on top of a dark background — and black-on-dark is difficult to see.
The fix is straightforward: watch for value changes and update the stylesheet to swap the text color at the right moment.
Styling the QProgressBar text
The text color on a QProgressBar is controlled by the color property on the QProgressBar selector itself — not on QProgressBar::chunk. The ::chunk sub-control only styles the filled portion of the bar (its background color, border, etc.), while color on QProgressBar sets the text color.
Here's a quick example of setting the text to white:
self.progress_bar.setStyleSheet("QProgressBar { color: white; }")
And setting it back to black:
self.progress_bar.setStyleSheet("QProgressBar { color: black; }")
Responding to value changes
QProgressBar emits a valueChanged signal every time its value updates. You can connect a slot to this signal that checks the current value and applies the appropriate stylesheet.
self.progress_bar.valueChanged.connect(self.update_progress_text_color)
Then define the slot:
Packaging Python Applications with PyInstaller by Martin Fitzpatrick — This step-by-step guide walks you through packaging your own Python applications from simple examples to complete installers and signed executables.
def update_progress_text_color(self, value):
if value > 50:
self.progress_bar.setStyleSheet("""
QProgressBar {
color: white;
}
""")
else:
self.progress_bar.setStyleSheet("""
QProgressBar {
color: black;
}
""")
Each time the value changes, this method checks whether it's above 50 and sets the text color accordingly.
Preserving other styles
If you already have a stylesheet on your progress bar (for example, customizing the chunk color or the bar's border), you'll want to include those properties in both branches so they aren't lost when the stylesheet is replaced. Every call to setStyleSheet() replaces the previous stylesheet entirely.
For example:
BASE_STYLE = """
QProgressBar {
border: 1px solid grey;
border-radius: 5px;
text-align: center;
}
QProgressBar::chunk {
background-color: #4CAF50;
border-radius: 5px;
}
"""
def update_progress_text_color(self, value):
if value > 50:
color_style = "QProgressBar { color: white; }"
else:
color_style = "QProgressBar { color: black; }"
self.progress_bar.setStyleSheet(BASE_STYLE + color_style)
Because the color_style rule comes after BASE_STYLE, it overrides the text color while keeping everything else intact.
Complete working example
Here's a full PyQt5 application you can copy and run. It uses a QTimer to increment the progress bar automatically so you can see the text color flip from black to white as the bar crosses 50%.
import sys
from PyQt5.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QProgressBar, QPushButton,
)
from PyQt5.QtCore import QTimer
BASE_STYLE = """
QProgressBar {
border: 1px solid grey;
border-radius: 5px;
text-align: center;
font-size: 14px;
}
QProgressBar::chunk {
background-color: #3874f2;
border-radius: 5px;
}
"""
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QProgressBar Text Color Demo")
self.resize(400, 120)
layout = QVBoxLayout()
self.setLayout(layout)
self.progress_bar = QProgressBar()
self.progress_bar.setMinimum(0)
self.progress_bar.setMaximum(100)
self.progress_bar.setValue(0)
self.progress_bar.setStyleSheet(BASE_STYLE + "QProgressBar { color: black; }")
layout.addWidget(self.progress_bar)
self.start_button = QPushButton("Start")
self.start_button.clicked.connect(self.start_progress)
layout.addWidget(self.start_button)
self.progress_bar.valueChanged.connect(self.update_progress_text_color)
self.timer = QTimer()
self.timer.timeout.connect(self.advance_progress)
def start_progress(self):
self.progress_bar.setValue(0)
self.timer.start(50)
def advance_progress(self):
current = self.progress_bar.value()
if current >= 100:
self.timer.stop()
return
self.progress_bar.setValue(current + 1)
def update_progress_text_color(self, value):
if value > 50:
color_style = "QProgressBar { color: white; }"
else:
color_style = "QProgressBar { color: black; }"
self.progress_bar.setStyleSheet(BASE_STYLE + color_style)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
When you run this, click Start and watch the percentage label. While the bar is at 50% or below, the text is black. The moment it passes 50%, the text switches to white, keeping it readable against the blue chunk.
You can adjust the threshold, the colors, or even add a gradual transition by checking at multiple thresholds — the same pattern applies. Connect to valueChanged, check the value, and set the stylesheet accordingly.