Wolf Vollprecht
Asylstrasse 127
8032 Zürich

TEL: +41 76 729 39 99

MAIL: w.vollprecht@gmail.com

python-gtk-css-titleimage.jpg

GTK, Python and CSS are an awesome combo

Wolf Vollprecht // 2 October 2012

I just wanted to put together a little list of things that are amazing about programming with Python, GTK and CSS, because it's so easy and at the same time some features are so undocumented that it really can be a pain for starters.

Basic setup

I am going to assume some familiarity with Python (otherwise, there are plenty of tutorials online, one noteable one is probably Learn Python The Hard Way). The best tutorial for Python and GTK3 is by the way this one: Python GTK 3 Tutorial.

So as such a basic GTK program might look like this:

#!/usr/bin/python
from gi.repository import Gtk, Gdk

win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

Note the usage of gi.repository to import GTK from, it's the GObject Introspection version of GTK that quickly, the rapid development tool for ubuntu (a little like ruby on rails for desktop applications) uses in its templates.

GTK 3 python is a slightly different from GTK 2 python, and one of the biggest differences is that one cannot use the default class constructor but needs to use the GTK provided ones which always include a .new() or .new_with_label('abc') and so on. Otherwise you might get a memory error.

How to namespace your window

Namespacing to the application window is quite handy, because otherwise all your widgets and dialogs will be affected by the stylesheet, which is not so good e.g. when you're using a filechooser-dialog.

You give your window a CSS-ID equivalent with

win.set_name('MyWindow')

Now it's possible to write CSS like this:

#MyWindow {
    background-color: #F00;
}

which would set the background of your window to a red, and is already a pretty cool effect.

How to load the CSS

In the next example, a GTK Window is created and a button is added to the GTK Toplevel window. Then some CSS is applied to style the window.

#!/usr/bin/python
from gi.repository import Gtk, Gdk

win = Gtk.Window()
win.set_name('MyWindow')

# The Button
button = Gtk.Button("Click Me")
win.add(button)


win.connect("delete-event", Gtk.main_quit)

style_provider = Gtk.CssProvider()

css = """
#MyWindow {
    background-color: #F00;
}
"""

style_provider.load_from_data(css)

Gtk.StyleContext.add_provider_for_screen(
    Gdk.Screen.get_default(), 
    style_provider,     
    Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)

win.show_all()
Gtk.main()

and we are already getting a red background (you can see the background by resizing the window, it will appear.

It is also possible to use nested selectors in GTK CSS:

#MyWindow GtkButton {
    background: #000;
    border-radius: 10px;
    border-color: #000;
    box-shadow: 0 0 5px #333 inset;
    margin: 10px;
}

and whatever you can imagine. Sky is the limit!

Transition and States

GTK also knows different states of the element: :insensitive, :hover or :prelight, :active and so on, there is a lot more on the reference website: Reference Website

It's even possible to make a nice fade out or fade in or whatever animation through setting different states on the element. For example, in UberWriter I have a statusbar that should fade out after 3 seconds of no mousemovement. In GTK 3.6 (on Ubuntu 12.10 that is) I can just set

self.status_bar.set_state_flags(Gtk.StateFlags.INSENSITIVE, True)

to fade the status bar out, if I have the right CSS for that (I am currently using a fade to background: rgba(255,255,255,0) and color: rgba(255,255,255,0)). You can add transitions to your element with transition: 0.2s ease-in. Note that you have to add the transition to the state, that you want to go to. E.g. you want to the hover-state, the transition property goes to #MyWindow GtkButton:hover{ transition: 0.2s ease-in; }.

How to load a CSS File into your GTK / Python app

Somehow, at least with ubuntu, it's not possible to directly load the CSS file with the convenience function Gtk.CssProvider.load_from_file. So what I did for Uberwriter is, reading the contents of the CSS file with python and then loading them into the app like this:

style_provider = Gtk.CssProvider()

css = open('/path/to/your/style.css'), 'rb') # rb needed for python 3 support
css_data = css.read()
css.close()

style_provider.load_from_data(css_data)

Gtk.StyleContext.add_provider_for_screen(
    Gdk.Screen.get_default(), style_provider,     
    Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)

More useful resources

  • GTK has a demo application called gtk3-demo. It's in ubuntus default repositories and installable via sudo apt-get install gtk-3-examples. There are around 5 examples for GTK with CSS and you see a lot of selectors in action and also an accordion with transitions. Unfortunatly, the »multiple background« examples don't work for me, on Ubuntu 12.10, because the CSS files somehow are not found (I guess it was a mistake in packaging the files). A short video highlighting these CSS examples is on the bottom of this post.
  • I recommend you look at the reset.css that ships with the GTK Examples, so you have some code to be able to style your app from scratch (e.g. you really don't want any of the ubuntu button styles)
  • Theming files from ubuntu are also always great for reference and to see which selectors work and how, which states are applied and so on. You can find them easily from terminal with locate gtk.css.
  • Again, on the reference website you'll also find lots and lots of information: Reference Website

Thanks

Thanks for reading, please send suggestions per Twitter or Mail!



For more blog posts on GTK, Python and much more you should follow me on Twitter!

And a last goodie

This short clip from youtube shows gtk3-demo in action