Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the selected item colour in a GtkTreeview using python

I have a dialog which contains a pygtk.treeview for listing tasks by priority. Each row has the background colour set based on that priority, so for example the highest priority has a light red background.

The row selection color is not so easy to change. I can set it using treeview.modify_base(gtk.STATE_SELECTED, "#C4C4C4"), but no colours work well with the colours used to enhance the concept of priority.

I had the idea to change the selection colour to be a slightly darker version of the colour used as the normal row background, so in the example above, that would be a darker red. I tried calling the function above in response to the treeselection's changed signal, and it works, but with heavy flickering.

Another idea was to change the selection to transparent and put a border around it instead, but as far as I can tell, this isn't possible.

  1. How can I change the selection colour in the way described above without the flickering?
  2. Can I change show the selection by having only a border around the row?

Note: I'm aware that this violates the theme selected by the user. I feel I have a good reason for it. Having the priority indicated by colour makes it instantly recognisable. The selection colour hides this. If you have alternative suggestions, I am open to them, but it needs to retain the ease at which a user can identify the priority.

like image 985
Jon Avatar asked Jun 23 '10 05:06

Jon


Video Answer


2 Answers

You can use the method described here – I have tested it briefly and it does the job without flickering. Basically, the trick is to use the "Markup" property of the cell renderer. There's one catch, though: if you want to change the background colour with this method, only the background behind the "actual" text is changed, not the whole row. However, if you want to change the text colour (with <span foreground= ... ), which was actually my intention, it looks ok.

I have the following CellDataFunc (this is C#, but I hope it's still useful):

private void CellDataFunc(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) {
    Item item = (Item) model.GetValue (iter, 0);
    if(cell is CellRendererText) {
        int id = (int)column.GetData("colId");
        string text = "";
        switch(id) {
            case 0: text = item.Name;  break;
            case 1: text = item.Size; break;
            case 2: text = item.Time.ToString();  break;                
        }
        //(cell as Gtk.CellRendererText).Text = text;
        if(item.Highlight) {
            (cell as Gtk.CellRendererText).Markup = 
                            "<span background=\"red\">"+text+"</span>";
        } else {
            (cell as Gtk.CellRendererText).Markup = text;
        }
    }
}
like image 188
rob74 Avatar answered Sep 26 '22 04:09

rob74


You could add a separate pixbuf cell (say, the same size as a small icon) to the far left to indicate selection. Selected rows could fill this with a more "solid" (saturated) version of the colour used for the background. For example. if you use a pink background for high priority, you could use red for the selection indicator. Or you could use an icon.

To implement this with the colour filling method:

  1. Disable the built-in highlighting as per Tobias' suggestion ("make the STATE_SELECTED color identical to STATE_NORMAL").
  2. Create a widget based on gtk.gdk.Pixbuf that allows you to create a solid area of colour, perhaps using the fill method.
  3. Use a CellRendererPixbuf for your "selection" cell.

You can then color or uncolour the "selection cell" upon selection changes to indicate which row is selected, or display an icon (eg. a stock symbol).

Note that I haven't implemented this, it's just an idea. It departs significantly from the usual GTK selection indication, so (obviously) use your judgement as to whether it's useable.

like image 38
detly Avatar answered Sep 24 '22 04:09

detly