Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make buttons different colours in Python GTK3 (using gi)?

My latest head-scratcher is to build a silly little app in Python3 using GTK3, with colours other than fog-grey on the buttons. I have spent the last few days googling for how to do this, and so far everything I have tried has failed. Not just failed, but failed silently, with no error messages to give me any clue as to what is going on.

This is my test app:

from gi.repository import Gtk, Gdk

class ButtonWindow(Gtk.Window):

    def __init__(self):
        super().__init__(title="Button Test")
        self.set_border_width(10)
        hbox = Gtk.Box(spacing=10)
        self.add(hbox)
        hbox.set_homogeneous(False)

        # make the button
        button = Gtk.Button('Test Button')
        hbox.pack_start(button, True, True, 0)

        # try to change its colour ....

#        button.modify_base(Gtk.StateType.NORMAL, Gdk.color_parse('green'))
#        button.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0, 1, 0, 1))
#        button.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0x00ff00))
#        button.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("green"))
#        button.modify_bg(Gtk.StateType.ACTIVE, Gdk.color_parse("green"))
#        button.modify_bg(Gtk.StateType.SELECTED, Gdk.color_parse("green"))

        # attempt to change the style ....

#        style = button.get_style().copy()
#        style.bg[Gtk.StateType.NORMAL] = Gdk.color_parse('green')
#        style.bg[Gtk.StateType.ACTIVE] = Gdk.color_parse('red')
#        style.bg[Gtk.StateType.SELECTED] = Gdk.color_parse('blue')
#        style.bg[Gtk.StateType.PRELIGHT] = Gdk.color_parse('black')
#        button.set_style(style)

        # ok, let's try changing the box ....

#        hbox.modify_base(Gtk.StateType.NORMAL, Gdk.color_parse('green'))
#        hbox.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0,1,0,1))
#        hbox.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0x00ff00ff))
#        hbox.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse('green'))

window = ButtonWindow()        
window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()

I have left my failed attempts in as comments. As noted above, as far as the application is concerned, it appears to have worked, because none of the above variations generate any error messages. However, none of them seem to work for me, because the buttons remain the colour of stale dishwater.

FYI I am using Python 3.2.3 under Ubuntu 12.04 with python3-gi and python3-gi-cairo installed from the standard repository.

Can someone please point me in the right direction?

EDIT: The following is a re-worked example based on @mike's answer. This works, but there are some issues with it, possibly to be addressed in some follow-up questions. The issues are:

  1. Why does background have to used on Ubuntu instead of background-color, and then only for the button?
  2. I still have some problems getting font styling to work, but at least now I have a working example to play with.
  3. Can different styles/colours be applied to different buttons, e.g. on the basis of the text or some other attribute?

So, the code:-

from gi.repository import Gtk, Gdk

class ButtonWindow(Gtk.Window):

    def __init__(self):
        super().__init__(title="Button Test")
        self.set_border_width(10)

        hbox = Gtk.Box(spacing=10)
        self.add(hbox)
        hbox.set_homogeneous(False)

        # make the button
        button = Gtk.Button('Test Button')
        hbox.pack_start(button, True, True, 0)

# get the style from the css file and apply it
cssProvider = Gtk.CssProvider()
cssProvider.load_from_path('gtkStyledButtonTest.css')
screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider,
                                     Gtk.STYLE_PROVIDER_PRIORITY_USER)

window = ButtonWindow()        
window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()

and the css file looks like this:-

GtkWindow {
    background-color: #0000ff;
}

GtkButton {
    color: #ff0000;
    background: #00ff00;
}

I hope someone finds this useful.

like image 825
Bobble Avatar asked Aug 13 '12 03:08

Bobble


1 Answers

Even though this is a old question, I'd like to add an answer referring to question 3 just for the reference.

GTK3 adds the concept of style classes. So to get different colored buttons you can address them directly be name or add a style class to its context. All this is explained in the links mike provided in his answer.

Here is a simple example how to use style classes to highlight invalid text in entries:

from gi.repository import Gtk, Gdk

class MainWindow(Gtk.Window):

    def __init__(self):
        super().__init__()
        vbox = Gtk.Box(spacing=10,orientation=Gtk.Orientation.VERTICAL)
        self.add(vbox)

        self.entries = [ Gtk.Entry() for i in range(3) ]
        for e in self.entries:
            vbox.pack_start(e, True, True, 0)
            e.connect("changed", self.on_entry_changed)
            e.set_text('123')

        button=Gtk.Button('ok',name='ok-button')
        vbox.pack_end(button,True,True,0)


    def on_entry_changed(self,entry):
        ctx = entry.get_style_context()
        if not entry.get_text().isnumeric():
            ctx.add_class('invalid')
        else:
            ctx.remove_class('invalid')


cssProvider = Gtk.CssProvider()
cssProvider.load_from_path('style.css')
screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider,
                                     Gtk.STYLE_PROVIDER_PRIORITY_USER)

window = MainWindow()
window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()

with style.css:

GtkEntry.invalid {
    background-color: #ffaaaa;
    background: #ffaaaa;
}

GtkButton#ok-button {
    background-color: green;
    background: green;
}
like image 66
buergi Avatar answered Sep 30 '22 02:09

buergi