how to write custom gtk.cellrenderer in python and gtk 3?

  • Last Update :
  • Techknowledgy :

Gtk.CellRenderer widgets are used to display information within widgets such as the Gtk.TreeView or Gtk.ComboBox. They work closely with the associated widgets and are very powerful, with lots of configuration options for displaying a large amount of data in different ways. There are seven Gtk.CellRenderer widgets which can be used for different purposes:,A Gtk.CellRendererCombo can operate in two modes. It can be used with and without an associated Gtk.Entry widget, depending on the value of the “has-entry” property.,A Gtk.CellRendererText renders a given text in its cell, using the font, color and style information provided by its properties. The text will be ellipsized if it is too long and the “ellipsize” property allows it.,The range of the spinbutton is taken from the adjustment property of the cell renderer, which can be set explicitly or mapped to a column in the tree model, like all properties of cell renders. Gtk.CellRendererSpin also has properties for the climb rate and the number of digits to display.

cell.set_property("editable", True)
 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
import gi

gi.require_version("Gtk", "3.0")
from gi.repository
import Gtk

class CellRendererTextWindow(Gtk.Window):
   def __init__(self):
   super().__init__(title = "CellRendererText Example")

self.set_default_size(200, 200)

self.liststore = Gtk.ListStore(str, str)
self.liststore.append(["Fedora", "https://fedoraproject.org/"])
self.liststore.append(["Slackware", "http://www.slackware.com/"])
self.liststore.append(["Sidux", "http://sidux.com/"])

treeview = Gtk.TreeView(model = self.liststore)

renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Text", renderer_text, text = 0)
treeview.append_column(column_text)

renderer_editabletext = Gtk.CellRendererText()
renderer_editabletext.set_property("editable", True)

column_editabletext = Gtk.TreeViewColumn(
   "Editable Text", renderer_editabletext, text = 1
)
treeview.append_column(column_editabletext)

renderer_editabletext.connect("edited", self.text_edited)

self.add(treeview)

def text_edited(self, widget, path, text):
   self.liststore[path][1] = text

win = CellRendererTextWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
import gi

gi.require_version("Gtk", "3.0")
from gi.repository
import Gtk

class CellRendererToggleWindow(Gtk.Window):
   def __init__(self):
   super().__init__(title = "CellRendererToggle Example")

self.set_default_size(200, 200)

self.liststore = Gtk.ListStore(str, bool, bool)
self.liststore.append(["Debian", False, True])
self.liststore.append(["OpenSuse", True, False])
self.liststore.append(["Fedora", False, False])

treeview = Gtk.TreeView(model = self.liststore)

renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Text", renderer_text, text = 0)
treeview.append_column(column_text)

renderer_toggle = Gtk.CellRendererToggle()
renderer_toggle.connect("toggled", self.on_cell_toggled)

column_toggle = Gtk.TreeViewColumn("Toggle", renderer_toggle, active = 1)
treeview.append_column(column_toggle)

renderer_radio = Gtk.CellRendererToggle()
renderer_radio.set_radio(True)
renderer_radio.connect("toggled", self.on_cell_radio_toggled)

column_radio = Gtk.TreeViewColumn("Radio", renderer_radio, active = 2)
treeview.append_column(column_radio)

self.add(treeview)

def on_cell_toggled(self, widget, path):
   self.liststore[path][1] = not self.liststore[path][1]

def on_cell_radio_toggled(self, widget, path):
   selected_path = Gtk.TreePath(path)
for row in self.liststore:
   row[2] = row.path == selected_path

win = CellRendererToggleWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35

Suggestion : 2

i must write my own cell renderer with button, i came up with this:

#!/usr/bin/env python3

from gi.repository
import Gtk

class CellRendererButton(Gtk.CellRenderer):
   def __init__(self):
   Gtk.CellRenderer.__init__(self)

def get_size(self, widget, cell_area):
   buttonHeight = cell_area.height
buttonWidth = buttonHeight
return (0, 0, buttonWidth, buttonHeight)

def render(self, window, widget, background_area, cell_area, expose_area, flags):
   style = widget.get_style()
x, y, buttonWidth, buttonHeight = self.get_size()
style.paint_box(window, widget.get_state(), Gtk.SHADOW_ETCHED_OUT, expose_area, widget, None, 0, 0, buttonWidth, buttonHeight)

class MyWindow(Gtk.Window):
   def __init__(self):
   Gtk.Window.__init__(self, title = 'T', default_width = 200, default_height = 300)
self.connect('destroy', self.__onDestroy)
self.__createGUI()
self.show_all()

def __createGUI(self):
   box = Gtk.Box(orientation = Gtk.Orientation.VERTICAL)
listStore = Gtk.ListStore(str, str)
treeView = Gtk.TreeView(listStore)
textRenderer = Gtk.CellRendererText()
textColumnA = Gtk.TreeViewColumn(None, textRenderer)
textColumnB = Gtk.TreeViewColumn(None, textRenderer)
buttonRenderer = CellRendererButton()
buttonColumn = Gtk.TreeViewColumn(None, buttonRenderer)
textColumnA.add_attribute(textRenderer, 'text', 0)
textColumnB.add_attribute(textRenderer, 'text', 1)
treeView.append_column(textColumnA)
treeView.append_column(textColumnB)
treeView.append_column(buttonColumn)
listStore.append(('my string', 'my string'))
self.add(treeView)

def __onDestroy(self, e):
   Gtk.main_quit()

t = MyWindow()
Gtk.main()

but its not working :/ I get lots of errors like:

(game.py: 4736): Gtk - CRITICAL **: gtk_cell_renderer_render: assertion `GTK_CELL_RENDERER_GET_CLASS (cell)->render != NULL' failed

Suggestion : 3

Gtk.CellRenderer — An object for rendering a single cell,There are a number of rules that must be followed when writing a new Gtk.CellRenderer. First and foremost, it’s important that a certain set of properties will always yield a cell renderer of the same size, barring a GtkStyle change. The Gtk.CellRenderer also has a number of generic properties that are expected to be honored by all children., Translates the cell renderer state to Gtk.StateFlags,based on the cell renderer and widget sensitivity, andthe given Gtk.CellRendererState., Passes an activate event to the cell renderer for possible processing. Some cell renderers may use events; for example, Gtk.CellRendererToggle toggles when it gets a mouse click.

Object Hierarchy:

    GObject╰── GInitiallyUnowned╰── Gtk.CellRenderer├── Gtk.CellRendererText├── Gtk.CellRendererPixbuf├── Gtk.CellRendererProgress├── Gtk.CellRendererSpinner╰── Gtk.CellRendererToggle

get_aligned_area()

get_aligned_area(self, widget: Gtk.Widget, flags: Gtk.CellRendererState, cell_area: Gdk.Rectangle) - > aligned_area: Gdk.Rectangle

get_size()

get_size(self, widget: Gtk.Widget, cell_area: Gdk.Rectangle = None) - > x_offset: int, y_offset: int, width: int, height: int

activate()

activate(self, event: Gdk.Event, widget: Gtk.Widget, path: str, background_area: Gdk.Rectangle, cell_area: Gdk.Rectangle, flags: Gtk.CellRendererState) - > bool

start_editing()

start_editing(self, event: Gdk.Event, widget: Gtk.Widget, path: str, background_area: Gdk.Rectangle, cell_area: Gdk.Rectangle, flags: Gtk.CellRendererState) - > Gtk.CellEditable

Suggestion : 4

Last Updated : 29 Aug, 2020

Text in Gtk.CellRendererText widget can be make editable by 

cell.set_property("editable", True)

Suggestion : 5

Three things you need to do in the course of that:,You can do this by writing a new object that derives from GtkCellRenderer (or even one of the other cell renderers if you just want to extend an existing one).,when you create the renderer, which sets all rows in that particular renderer column to be editable.,With this setup, the cell renderer’s properties are ‘loaded’ from the model before each cell is rendered.

GtkListStore * list_store;

list_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_UINT);
void
onTreeViewRowActivated(GtkTreeView * view,
   GtkTreePath * path,
   GtkTreeViewColumn * col,
   gpointer userdata) {
   GtkTreeModel * model = gtk_tree_view_get_model(view);

   GtkTreeIter iter;
   if (gtk_tree_model_get_iter(model, & iter, path)) {
      char * name;

      gtk_tree_model_get(model, & iter, COL_NAME, & name, -1);

      g_print("The row containing the name '%s' has been double-clicked.\n", name);

      g_free(name);
   }
}
void
traverse_list_store(GtkListStore * liststore) {
   GtkTreeIter iter;
   gboolean valid;

   g_return_if_fail(liststore != NULL);

   /* Get first row in list store */
   valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(liststore), & iter);

   while (valid) {
      /* ... do something with that row using the iter ...          */
      /* (Here column 0 of the list store is of type G_TYPE_STRING) */
      gtk_list_store_set(liststore, & iter, 0, "Joe", -1);

      /* Make iter point to the next row in the list store */
      valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(liststore), & iter);
   }
}
GtkListStore * liststore;
GtkTreeIter iter;

liststore = gtk_list_store_new(1, G_TYPE_STRING);

/* Append an empty row to the list store. Iter will point to the new row */
gtk_list_store_append(liststore, & iter);

/* Append an empty row to the list store. Iter will point to the new row */
gtk_list_store_append(liststore, & iter);

/* Append an empty row to the list store. Iter will point to the new row */
gtk_list_store_append(liststore, & iter);
GtkListStore * treestore;
GtkTreeIter iter, child;

treestore = gtk_tree_store_new(1, G_TYPE_STRING);

/* Append an empty top-level row to the tree store.
 *  Iter will point to the new row */
gtk_tree_store_append(treestore, & iter, NULL);

/* Append another empty top-level row to the tree store.
 *  Iter will point to the new row */
gtk_tree_store_append(treestore, & iter, NULL);

/* Append a child to the row we just added.
 *  Child will point to the new row */
gtk_tree_store_append(treestore, & child, & iter);

/* Get the first row, and add a child to it as well (could have been done
 *  right away earlier of course, this is just for demonstration purposes) */
if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(treestore), & iter)) {
   /* Child will point to new row */
   gtk_tree_store_append(treestore, & child, & iter);
} else {
   g_error("Oops, we should have a first row in the tree store!\n");
}

Suggestion : 6

There are a number of rules that must be followed when writing a new Gtk.CellRenderer. First and foremost, it’s important that a certain set of properties will always yield a cell renderer of the same size, barring a Gtk.Style change. The Gtk.CellRenderer also has a number of generic properties that are expected to be honored by all children.,Informs the cell renderer that the editing is stopped. If canceled is True, the cell renderer will emit the Gtk.CellRenderer ::editing-canceled signal.,Obtains the width and height needed to render the cell. Used by view widgets to determine the appropriate size for the cell_area passed to Gtk.CellRenderer.render(). If cell_area is not None, fills in the x and y offsets (if set) of the cell relative to this location.,Translates the cell renderer state to Gtk.StateFlags, based on the cell renderer and widget sensitivity, and the given Gtk.CellRendererState.

static void
text_editing_started(GtkCellRenderer * cell,
   GtkCellEditable * editable,
   const gchar * path,
      gpointer data) {
   if (GTK_IS_ENTRY(editable)) {
      GtkEntry * entry = GTK_ENTRY(editable);

      // ... create a GtkEntryCompletion

      gtk_entry_set_completion(entry, completion);
   }
}

Suggestion : 7

The properties of a CellRenderer determine how the data will be rendered:,The above properties are available for all CellRenderer subclasses. The individual CellRenderer types also have their own properties.,The cellrenderer.py program illustrates the application of editable CellRendererText and activatable CellRendererToggle cells in a TreeStore.,sets the CellRenderer background to the color specified by the string in the second column of the data store.

  treeviewcolumn.add_attribute(cell_renderer, attribute, column)
  treeviewcolumn.add_attribute(cell, "cell-background", 1)
  treeviewcolumn.set_attributes(cell_renderer, ...)
  treeviewcolumn.set_attributes(cell, text = 0, cell_background = 1, xpad = 3)
  treeviewcolumn.clear_attributes(cell_renderer)
  treeviewcolumn.set_cell_data_func(cell_renderer, func, data = None)

Suggestion : 8

.CellRendererText()

def makeColumn(name, index, onedit = None, cell = None, links = None):
   ""
"
Return a
default "TreeViewColumn" of name "name"
whose TreeModel index
for the renderer is "index"
""
"
if cell == None:
   cell = gtk.CellRendererText()
if links == None:
   links = {
      "text": index
   }
if onedit:
   cell.set_property("editable", True)
cell.connect("edited", onedit)
col = gtk.TreeViewColumn(name, cell, ** links)
col.set_property("clickable", True)
col.set_property("reorderable", True)
col.set_property("resizable", True)
col.set_property("sizing", 1)
col.set_property("sort-indicator", True)
col.set_sort_column_id(index)
return col
def __init__(self):
   super(ShowLastPackets.PacketList, self).__init__()
self.set_properties(hscrollbar_policy = gtk.POLICY_AUTOMATIC,
   vscrollbar_policy = gtk.POLICY_AUTOMATIC)
self.table_model = gtk.ListStore( * ([str] * 4))
treeview = gtk.TreeView(self.table_model)
treeview.show()
self.add(treeview)

def add_column(descr, colid):
   column = gtk.TreeViewColumn(descr, gtk.CellRendererText(), text = colid)
treeview.append_column(column)

add_column("Time", self.COLUMN_TIME)
add_column("Interface", self.COLUMN_INTERFACE)
add_column("Size", self.COLUMN_SIZE)
add_column("Contents", self.COLUMN_CONTENTS)
def inflate_list_store_combo(model_data, combo_widget):
   ""
"inflates an individual combo box
Args:
   model_data: data to be loaded into a list store(list)
combo_widget: the widget to load data into.
""
"
empty = True
if combo_widget.get_model():
   empty = False
list_store = gtk.ListStore(str)
for datum in model_data:
   list_store.append([datum])

combo_widget.set_model(list_store)

if empty:
   renderer = gtk.CellRendererText()
combo_widget.pack_start(renderer, expand = True)
combo_widget.add_attribute(renderer, "text", 0)
def __init__(self):
   ""
"
Initializer
@param self this object
   ""
"
super(ShowLastPackets.PacketList, self).__init__()
self.set_properties(hscrollbar_policy = gtk.POLICY_AUTOMATIC,
   vscrollbar_policy = gtk.POLICY_AUTOMATIC)
self.table_model = gtk.ListStore( * ([str] * 4))
treeview = gtk.TreeView(self.table_model)
treeview.show()
self.add(treeview)

def add_column(descr, colid):
   column = gtk.TreeViewColumn(descr, gtk.CellRendererText(), text = colid)
treeview.append_column(column)

add_column("Time", self.COLUMN_TIME)
add_column("Interface", self.COLUMN_INTERFACE)
add_column("Size", self.COLUMN_SIZE)
add_column("Contents", self.COLUMN_CONTENTS)
def __init__(self, o = None):
   self.xml = x = gtk.glade.XML(sibpath(__file__, "inspectro.glade"))
self.tree_view = x.get_widget("treeview")
colnames = ["Name", "Value"]
for i in range(len(colnames)):
   self.tree_view.append_column(
      gtk.TreeViewColumn(
         colnames[i], gtk.CellRendererText(), text = i))
d = {}
for m in reflect.prefixedMethods(self, "on_"):
   d[m.im_func.__name__] = m
self.xml.signal_autoconnect(d)
if o is not None:
   self.inspect(o)
self.ns = {
   'inspect': self.inspect
}
iwidget = x.get_widget('input')
self.input = ConsoleInput(iwidget)
self.input.toplevel = self
iwidget.connect("key_press_event", self.input._on_key_press_event)
self.output = ConsoleOutput(x.get_widget('output'))
def __init__(self, rfunction):
   super(FunctionPanel, self).__init__()
self._rfunction = rfunction
formals = self._as_list(rfunction.formals())
formals_value = [x
   for x in formals.rx(-1)
]
formals_name = [x
   for x in formals.rx(-1).names
]
self._table = gtk.ListStore(str, str)
self._treeView = gtk.TreeView(model = self._table)
self._treeView.show()
self._valueColumns = [gtk.TreeViewColumn('parameter'),
   gtk.TreeViewColumn('value'),
]
self._valueCells = []
for col_i, col in enumerate(self._valueColumns):
   self._treeView.append_column(col)
cr = gtk.CellRendererText()
col.pack_start(cr, True)
self._valueCells.append(cr)
col.set_attributes(cr, text = col_i)

for name, value in itertools.izip(formals_name, formals_value):
   row = (name, value)
self._table.append(row)

sbox = gtk.HBox(homogeneous = False, spacing = 0)
sbox.show()