Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show icon or color in Gtk TreeView tree

I am having difficulty loading a file or displaying a colour in one of the columns of a Gtk TreeView (Python binding of GTK3). An example taken from QGIS shows a icon in the first row and a blue circle in the second row. The colour is taken from the layer properties:

enter image description here

My code looks like this but does not load the icon.png file in the same directory:

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

class MyWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_default_size(200, 200)

        self.liststore = Gtk.ListStore(GdkPixbuf.Pixbuf, str)
        self.treeview = Gtk.TreeView(model=self.liststore)

        symbol1 = GdkPixbuf.Pixbuf.new_from_file("icon.png")
        self.liststore.append([symbol1, "This is a symbol1"])

        symbol2 = Gtk.IconTheme.get_default().load_icon("gtk-cut", 64, 0)
        self.liststore.append([symbol2, "This is symbol2"])

        px_renderer = Gtk.CellRendererPixbuf()
        px_column = Gtk.TreeViewColumn("Icon", px_renderer)
        self.treeview.append_column(px_column) 

        str_renderer = Gtk.CellRendererText()
        str_column = Gtk.TreeViewColumn("Name", str_renderer, text=1)
        self.treeview.append_column(str_column)

        self.add(self.treeview)

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

The documentation for GTK3 pixbuf is here:

  • https://lazka.github.io/pgi-docs/index.html#GdkPixbuf-2.0/classes/Pixbuf.html

Older examples for PyGTK are here, but something has really changed in how this is handled:

  • http://faq.pygtk.org/index.py?file=faq13.006.htp&req=show
  • http://www.daa.com.au/pipermail/pygtk/2003-August/005644.html
like image 813
tobias47n9e Avatar asked Jan 02 '15 16:01

tobias47n9e


3 Answers

This problem can resolve similar as PyGTK2.0, you need to attach two objects of CellRendererText and CellRendererPixbuf on the one object of TreeViewColumn and then call set_cell_data_func method of column to set data returner function of cells. this is tiny complex(see below code):

from gi.repository import Gtk, Gdk, GdkPixbuf

class MyWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_default_size(200, 200)

        self.liststore = Gtk.ListStore(str, str)
        self.treeview = Gtk.TreeView(model=self.liststore)

        self.liststore.append(["icon.png", "This is a symbol1"])

        px_renderer = Gtk.CellRendererPixbuf()
        px_column = Gtk.TreeViewColumn('')
        px_column.pack_start(px_renderer, False)
        str_renderer = Gtk.CellRendererText()
        px_column.pack_start(str_renderer, False)
        # set data connector function/method
        px_column.set_cell_data_func(px_renderer, self.get_tree_cell_pixbuf)
        px_column.set_cell_data_func(str_renderer, self.get_tree_cell_text)
        self.treeview.append_column(px_column)

        self.add(self.treeview)

    def get_tree_cell_text(self, col, cell, model, iter, user_data):
        cell.set_property('text', model.get_value(iter, 1))

    def get_tree_cell_pixbuf(self, col, cell, model, iter, user_data):
        cell.set_property('pixbuf', GdkPixbuf.Pixbuf.new_from_file(model.get_value(iter, 0)))

if __name__ == '__main__':
    win = MyWindow()
    win.connect("delete-event", Gtk.main_quit)
    win.show_all()
    Gtk.main()

you can use documents of pygtk2.0 about TreeViewColumn.set_cell_data_func method and read important page about CellRenderers and special properties of PyGTK2.0 that can useful on version 3 of PyGTK :)

like image 182
M.javid Avatar answered Nov 05 '22 08:11

M.javid


Here is a complete example of how to create a tree store with icons (credit goes to Ryan Paul):

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk
from gi.repository import Gdk as gdk
from gi.repository import GdkPixbuf
import os, stat

# Instantiate the tree store and specify the data types
store = gtk.TreeStore(str, GdkPixbuf.Pixbuf, int, bool)

def dirwalk(path, parent=None):
  # Iterate over the contents of the specified path
  for f in os.listdir(path):
    # Get the absolute path of the item
    fullname = os.path.join(path, f)
    # Extract metadata from the item
    fdata = os.stat(fullname)
    # Determine if the item is a folder
    is_folder = stat.S_ISDIR(fdata.st_mode)
    # Generate an icon from the default icon theme
    img = gtk.IconTheme.get_default().load_icon(
        "folder" if is_folder else "document",
        gtk.IconSize.MENU, 0)
    # Append the item to the TreeStore
    li = store.append(parent, [f, img, fdata.st_size, is_folder])
    # If the item is a folder, descend into it
    if is_folder: dirwalk(fullname, li)

dirwalk("/path/to/folder")

# Create a TreeViewColumn
col = gtk.TreeViewColumn("File")
# Create a column cell to display text
col_cell_text = gtk.CellRendererText()
# Create a column cell to display an image
col_cell_img = gtk.CellRendererPixbuf()
# Add the cells to the column
col.pack_start(col_cell_img, False)
col.pack_start(col_cell_text, True)
# Bind the text cell to column 0 of the tree's model
col.add_attribute(col_cell_text, "text", 0)
# Bind the image cell to column 1 of the tree's model
col.add_attribute(col_cell_img, "pixbuf", 1)

# Create the TreeView and set our data store as the model
tree = gtk.TreeView(store)
# Append the columns to the TreeView
tree.append_column(col)

scroll = gtk.ScrolledWindow()
scroll.add(tree)

window = gtk.Window()
window.connect("destroy", gtk.main_quit)
window.add(scroll)
window.set_default_size(400,400)
window.show_all()
gtk.main()

output

like image 4
jackw11111 Avatar answered Nov 05 '22 08:11

jackw11111


Apparently all I was missing was "pixbuf = 0" indicating that the pixbuf is in the 0th column. This line of the example needs to be modified:

    px_column = Gtk.TreeViewColumn("Icon", px_renderer, pixbuf=0)
like image 2
tobias47n9e Avatar answered Nov 05 '22 09:11

tobias47n9e