KiLauncher and Qt Stylesheets

The default theme of KiLauncher

The default theme for KiLauncher. Ok, so it kind of looks like your gramma’s formica breakfast table from the 1970s.

I’ve been doing a lot of tinkering on my KiLauncher project over the last week or so, and it’s not only shaping up into a nice useful little application, but an educational opportunity as well

My goals for KiLauncher were to make it both theme-able, and configurable with plain-text files.  The natural mechanism for this (for the theme, anyway) was CSS, a format with which any self-respecting UI designer is familiar.  Fortunately, Qt supports a subset of CSS to style its GUI classes, sometimes referred to as QSS.

Now, I’d used snippets of stylesheet before to configure individual widgets in Qt applications when it was simpler than messing about with Qt’s regular style classes, just by calling “setStyleSheet” on a widget like so:

someWidget.setStyleSheet("color:red; background-color: blue; border: 8px dashed teal;")

This works fine, but of course I wanted the whole application to be configurable from a single, external document.  I was pleased to find that child widgets of a QWidget can be styled by referencing their class names and applying the stylesheet to the parent widget.  For instance, if I had a set of QPushButtons on “someWidget”, I could style them like so:

someWidget.setStyleSheet("""
                           QPushButton {color: yellow; background-color: black; border: 1px groove lemonchiffon;}
                          """)

Armed with this information, I could simply read in an external file and apply it to the top-level Widget class.  This initially worked well, but where it started to get hairy was in making selectors that targeted the correct widgets.  For example, the labels on my buttons were a pair of QLabel widgets (one for the title, one for description) on a QWidget on a LaunchButton (a custom class subclassed from QPushButton).   So selecting them for styling looked like:

LaunchButton QWidget QLabel { font-family: comic sans; font-weight: bold }

And even then, I couldn’t access the title and description separately since they were both QLabels.  I couldn’t reasonably expect an end user (even the kind of end user who wants to write a custom theme for a Linux-based kiosk) to figure out the widget hierarchy of my application, so what I really needed was a way to attach user-friendly handles on different widgets the way you can add an “id” to a DOM node for easy CSS selection.

It’s not terribly well documented (I had to infer it from comments on a Qt developer’s blog and a stackexchange thread), but you can do this quite easily using the “setObjectName()” method that is inherited by just about every class in Qt.  So, having done this in the code:

myPushButton = QPushButton("Push Me!")
myPushButton.setObjectName("pushMeButton")

I could then do this in my CSS file:

#pushMeButton { color: brown; background-color: orange; border: solid 3px blue; }

Using this method, I made nice, user-friendly handles for all the relevant objects in my application. One important difference between objectNames and DOM ids is that objectNames apparently don’t need to be unique. Applying a common objectName to all instances of a class allows you to style them all, as you might a DOM class.

This makes KiLauncher easy to style for just about anyone who’s ever worked with CSS for the web. The only real difference is figuring out exactly what tags widgets support — sadly, it seems they always support just a few less than you’d like :-|.

Leave a Reply

Your email address will not be published.