Search code examples
qtpyqtqt5pyqt5qstyle

Dark theme for Qt widgets?


Background

I'm building a PyQt5 application, that I'd like to have a dark theme for. Previously I've worked with Android development where there was a dark theme that I could set for a whole application

Question

Is there a dark theme built into Qt (that applies to all widgets in an application, and that is cross-platform)?


Solution

  • No, but you may use my fairly comprehensive stylesheets that should look excellent on most platforms (it's inspired by KDE's Breeze Theme, which is a dark theme that is quite elegant). This was (hard) forked from the excellent QDarkStylesheet, which I felt had theme issues in numerous areas, so I modified it extensively for my own needs and added a light theme.

    Simple Use

    A sample of the theme is here. To use it in PyQt5, simply add the following lines to a project:

    import sys
    from PyQt5.QtCore import QFile, QTextStream
    from PyQt5.QtWidgets import QApplication
    import breeze_resources
    
    app = QApplication(sys.argv)
    file = QFile(":/dark.qss")
    file.open(QFile.ReadOnly | QFile.Text)
    stream = QTextStream(file)
    app.setStyleSheet(stream.readAll())
    

    enter image description here

    Dynamic Stylesheet Toggling

    In response to a comment, the easiest way to adjust the stylesheet to use either the light or the dark stylesheet dynamically is to wrap it in a function. You may then use the function as a slot to a Qt signal (warning: I primarily develop using C++, so there may be small errors in my code for the signal/slot mechanism).

    def toggle_stylesheet(path):
        '''
        Toggle the stylesheet to use the desired path in the Qt resource
        system (prefixed by `:/`) or generically (a path to a file on
        system).
    
        :path:      A full path to a resource or file on system
        '''
    
        # get the QApplication instance,  or crash if not set
        app = QApplication.instance()
        if app is None:
            raise RuntimeError("No Qt Application found.")
    
        file = QFile(path)
        file.open(QFile.ReadOnly | QFile.Text)
        stream = QTextStream(file)
        app.setStyleSheet(stream.readAll())
    

    Now we can add generic application logic that can use this function in a signal/slot mechanism (using a lambda as a convenient wrapper, if needed, to provide the path to the stylesheet toggler):

    # add logic for setting up application
    app = QApplication(sys.argv)
    # more logic for creating top-level widgets, application logic ...
    
    parent = ...
    light_btn = QPushButton("Toggle light.", parent)
    light_btn.clicked.connect(lambda: toggle_stylesheet(":/light.qss"))
    
    dark_btn = QPushButton("Toggle dark.", parent)
    dark_btn.clicked.connect(lambda: toggle_stylesheet(":/dark.qss"))
    
    # add to the layout, do other stuff
    # ...
    
    # end the Qt application
    sys.exit(app.exec_())
    

    This allows users to dynamically change the theme of an application developed with PyQt5 (or using analogous logic in C++, Qt5) to either a light or dark theme.

    Disclaimer: Obviously I am the maintainer.