2025, Dec 23 03:00

How to Fix PyQt5 QComboBox Popup Styling with Fusion: Apply the QSS Stylesheet on QApplication

Fix PyQt5 QComboBox popup white background under Fusion. Learn why QSS scoping fails and how applying the stylesheet to QApplication ensures consistent visuals.

Styling QComboBox in PyQt5 often looks straightforward until the popup opens and you’re greeted by a bright rectangle, wrong background color and a shifted list compared to the default look. This typically shows up when combining a custom QSS with the Fusion style. Below is a minimal example that reproduces the issue and a clean fix that doesn’t compromise the rest of your UI theme.

The setup that triggers the problem

The following code applies a stylesheet on the main window. When the combo box opens, the popup has a mismatched white background and odd spacing; turning off Fusion partially hides it but also removes styling you might rely on. The stylesheet here is based on the Blender-inspired theme credited in the original context.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QComboBox, QVBoxLayout, QWidget
class AppFrame(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QComboBox Demo")
        self.setGeometry(100, 100, 300, 200)
        rootPanel = QWidget()
        self.setCentralWidget(rootPanel)
        vbox = QVBoxLayout(rootPanel)
        codecList = [
            "BMP", "Iris", "PNG", "JPEG", "JPEG 2000", "Targa", "Targa Raw"
        ]
        formatSelector = QComboBox()
        formatSelector.addItems(codecList)
        formatSelector.setCurrentIndex(-1)
        vbox.addWidget(formatSelector)
        vbox.addStretch()
        qssTheme = """
        QWidget {
            background-color: #404040;
            color: #e6e6e6;
            margin: 0px;
        }
        QComboBox {
            background-color: #2c2c2c;
            border: 1px solid #404040;
            color: #d0d0d0;
            padding: 4px 6px;
            border-radius: 4px;
            margin: 0px;
        }
        QComboBox:disabled {
            background-color: #323232;
            color: #8a8a8a;
        }
        QComboBox::down-arrow {
            background-color: #2c2c2c;
            image: url('images/QComboBox_down_arrow.png');
        }
        QComboBox::down-arrow:on {
            background-color: #5680c2;
        }
        QComboBox::drop-down {
            background-color: #202020;
            border: none;
            width: 20px;
        }
        QComboBox:on {
            background-color: #5680c2;
            color: #f8f9f9;
        }
        QComboBox QAbstractItemView {
            background-color: #232323;
            border: 1px solid #404040;
            color: #d0d0d0;
            border-radius: 4px;
            margin: 0px;
            padding: 2px;
            min-width: 100px;
            selection-background-color: #5680c2;
        }
        """
        self.setStyleSheet(qssTheme)
if __name__ == "__main__":
    app = QApplication(sys.argv + ['-platform', 'windows:darkmode=1'])
    app.setStyle('Fusion')
    frame = AppFrame()
    frame.show()
    sys.exit(app.exec_())

What’s actually happening

The surprising part is not the QComboBox itself but its popup. That popup is a separate, top level widget. It doesn’t fully inherit the stylesheet from the combo box. The internal QStyleSheetStyle only applies a subset of rules to the popup container and relies on the active style for the rest. When Fusion is active, that default behavior shows through as an unexpected white rectangle and altered metrics.

The popup only partially inherits the combobox stylesheet because it’s top level; some rules are applied by QStyleSheetStyle, while other aspects fall back to the default style. Applying the stylesheet at the application level makes it effective for all widgets, including the popup.

This also explains why disabling Fusion partially improves the visuals while sacrificing parts of the desired theme. You’re just changing what the fallback looks like, not fixing the source of the mismatch.

The fix: apply the QSS at the application level

Instead of setting the stylesheet on the window, set it on QApplication. That way, the QSS is considered for every widget, including top level popups created by QComboBox. The following version produces an acceptable result without losing Fusion or your custom styles.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QComboBox, QVBoxLayout, QWidget
class AppFrame(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QComboBox Demo")
        self.setGeometry(100, 100, 300, 200)
        rootPanel = QWidget()
        self.setCentralWidget(rootPanel)
        vbox = QVBoxLayout(rootPanel)
        codecList = [
            "BMP", "Iris", "PNG", "JPEG", "JPEG 2000", "Targa", "Targa Raw"
        ]
        formatSelector = QComboBox()
        formatSelector.addItems(codecList)
        formatSelector.setCurrentIndex(-1)
        vbox.addWidget(formatSelector)
        vbox.addStretch()
if __name__ == "__main__":
    qssTheme = """
                    QWidget {
                        background-color: #404040;
                        color: #e6e6e6;
                        margin: 0px;
                    }
                    QComboBox {
                        background-color: #2c2c2c;
                        border: 1px solid #404040;
                        color: #d0d0d0;
                        padding: 4px 6px;
                        border-radius: 4px;
                        margin: 0px;
                    }
                    QComboBox:disabled {
                        background-color: #323232;
                        color: #8a8a8a;
                    }
                    QComboBox::down-arrow {
                        background-color: #2c2c2c;
                        image: url('images/QComboBox_down_arrow.png');
                    }
                    QComboBox::down-arrow:on {
                        background-color: #5680c2;
                    }
                    QComboBox::drop-down {
                        background-color: #202020;
                        border: none;
                        width: 20px;
                    }
                    QComboBox:on {
                        background-color: #5680c2;
                        color: #f8f9f9;
                    }
                    QComboBox QAbstractItemView {
                        background-color: #232323;
                        border: 1px solid #404040;
                        color: #d0d0d0;
                        border-radius: 4px;
                        margin: 0px;
                        padding: 2px;
                        min-width: 100px;
                        selection-background-color: #5680c2;
                    }
                    """
    app = QApplication(sys.argv + ['-platform', 'windows:darkmode=1'])
    app.setStyleSheet(qssTheme)
    app.setStyle('Fusion')
    frame = AppFrame()
    frame.show()
    sys.exit(app.exec_())

Why this matters

Complex desktop themes often mix QSS rules with a platform style like Fusion. Controls that spawn their own top level popups, like QComboBox, can appear inconsistent if the stylesheet is scoped too narrowly. Applying QSS at the application level prevents mismatched backgrounds, offsets, and other visual artifacts without requiring you to drop the style you need elsewhere.

Takeaways

If you see an incorrect background or layout shift when a QComboBox opens, check where your stylesheet is applied. The popup is a top level widget and only partially inherits styles from the combo box hierarchy. Setting the stylesheet on QApplication ensures consistent rendering for both the control and its popup while keeping Fusion active. If your theme is derived from a third-party QSS, keep it, but promote the application of that QSS to the app level for predictable results.