{"id":20,"date":"2007-01-27T12:20:41","date_gmt":"2007-01-27T10:20:41","guid":{"rendered":"http:\/\/blog.rastersoft.com\/index.php\/2007\/01\/27\/trabajando-con-gtktreeview-en-python\/"},"modified":"2015-08-15T18:11:43","modified_gmt":"2015-08-15T18:11:43","slug":"trabajando-con-gtktreeview-en-python","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=20","title":{"rendered":"Trabajando con GtkTreeView en Python"},"content":{"rendered":"<p>Esta semana tuve que trabajar en serio con el widget GtkTreeView en Python y se me hizo completamente cuesta arriba hasta que, despu\u00e9s de buscar en m\u00faltiples tutoriales y pelearme con el c\u00f3digo, me vino una epifan\u00eda y entend\u00ed su complejo pero potente esquema de funcionamiento; as\u00ed que, en base a la experiencia adquirida, voy a escribir un peque\u00f1o tutorial, acompa\u00f1ado de algo de c\u00f3digo para ejemplificar.<\/p>\n<p>En GtkTreeView tenemos una clara divisi\u00f3n entre los datos, la presentaci\u00f3n y el motor. Esto es lo que hace que sea un poco lioso al principio, pero tambi\u00e9n le da una potencia y versatilidad sorprendente.<\/p>\n<p>Lo primero que necesitamos es a\u00f1adir los m\u00f3dulos gtk, pygtk, gtk.glade y gobject. El \u00faltimo es necesario para los tipos de datos que vamos a manejar.<\/p>\n<p>A continuaci\u00f3n tenemos el widget <a href=\"http:\/\/www.pygtk.org\/docs\/pygtk\/class-gtktreeview.html\">GtkTreeView<\/a>. Este elemento es el que mostrar\u00e1 nuestra lista de datos. Obtenemos un puntero a dicho objeto mediante GLADE:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">treeview = arbol_xml.get_widget(\"nuestro_gtktreeview\")<\/pre>\n<\/div>\n<p>Ahora vamos a definir los tipos de datos que contendr\u00e1 cada fila. A \u00e9sto se le denomina <strong>modelo<\/strong>. Es importante entender que no todos los campos del modelo tienen por qu\u00e9 ser visibles. En este ejemplo vamos a reservar un entero para saber, cuando el usuario marque una opci\u00f3n, cual es la que est\u00e1 escogiendo. Tambi\u00e9n habr\u00e1 tres cadenas, que contendr\u00e1n el texto que queremos mostrar en el TreeView y el color de una de ellas.<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">modelo = gtk.ListStore (gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)<\/pre>\n<\/div>\n<p>Existen dos tipos de modelos: <a href=\"http:\/\/www.pygtk.org\/docs\/pygtk\/class-gtkliststore.html\">ListStore<\/a> y <a href=\"http:\/\/www.pygtk.org\/docs\/pygtk\/class-gtktreestore.html\">TreeStore<\/a>. Ambos se manejan pr\u00e1cticamente igual, salvo que el segundo permite tener elementos anidados en forma de arbol. La diferencia principal se da a la hora de a\u00f1adir los datos en s\u00ed, como veremos luego.<\/p>\n<p>El siguiente paso es asociar el modelo al TreeView, de manera que \u00e9ste sepa qu\u00e9 datos almacenar en cada fila:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">treeview.set_model(modelo)<\/pre>\n<\/div>\n<p>Hasta aqu\u00ed hemos definido los tipos de datos (mediante el modelo), y tenemos el motor (el TreeView), por lo que s\u00f3lo nos falta la presentaci\u00f3n. Para ello tenemos que usar dos clases m\u00e1s para definir cada una de las columnas que mostraremos:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">render=gtk.CellRendererText() # renderer para la primera columna\r\ncolumna = gtk.TreeViewColumn (\"titulo\", render, text=1, background=2) # primera columna de datos\r\ntreeview.append_column (columna)\r\n\r\nrender2=gtk.CellRendererText()\r\ncolumna2 = gtk.TreeViewColumn (\"otro titulo\", render2, text=3) # segunda columna de datos\r\ntreeview.append_column(columna2)<\/pre>\n<\/div>\n<p><a href=\"http:\/\/www.pygtk.org\/docs\/pygtk\/class-gtkcellrenderertext.html\">CellRendererText<\/a> es una clase encargada de mostrar un texto en una columna de un TreeView. En el ejemplo vemos que creamos dos de ellos, uno para cada columna que vamos a mostrar. Luego, creamos una <a href=\"http:\/\/www.pygtk.org\/docs\/pygtk\/class-gtktreeviewcolumn.html\">TreeViewColumn<\/a> que tendr\u00e1 varios par\u00e1metros: el primero es el t\u00edtulo que se mostrar\u00e1 en la parte superior del TreeView para dicha columna (si estamos mostrando los nombres de personas, el t\u00edtulo podr\u00eda ser <strong>nombre<\/strong>, por ejemplo), y el segundo es la referencia al tipo de CellRenderer que vamos a utilizar para esa columna (en este caso, como es texto, un CellRendererText, pero hay <a href=\"http:\/\/www.pygtk.org\/docs\/pygtk\/index.html\">m\u00e1s tipos<\/a>). El resto de par\u00e1metros depende del CellRenderer que estemos utilizando. En el caso del CellRendererText tenemos, entre otros, el par\u00e1metro <strong>text<\/strong>, que contendr\u00e1 el texto que queremos mostrar, y el par\u00e1metro <strong>background<\/strong>, que contiene el color del texto en formato de cadena de texto.<\/p>\n<p>Vemos que en la primera columna le asociamos el valor 1 para el texto y el 2 para el color de fondo, y para la segunda columna usamos el valor 3 para el texto. Estos valores se refieren a la variable correspondiente del modelo TreeStore que generamos unos pasos antes: la variable 0 es el entero, la 1 y la 2 son los dos strings que contendr\u00e1n, respectivamente, el texto y el color de la primera columna, y la 3 el texto de la segunda columna.<\/p>\n<p>Tras crear cada una de las columnas la a\u00f1adimos a nuestro TreeView mediante el m\u00e9todo <strong>append_column<\/strong>, con lo que nuestro TreeView estar\u00e1 listo para ser rellenado con los datos que deseemos. Esto lo hacemos de la siguiente manera:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">iterador = modelo.insert(posicion) # el iterador es el objeto que contiene todos los valores de una fila concreta\r\nmodelo.set_value(iterador,0,0) # el segundo cero es el dato que metemos (un entero)\r\nmodelo.set_value(iterador,1,\"Un texto\")\r\nmodelo.set_value(iterador,2,\"#00FFE0\")\r\nmodelo.set_value(iterador,3,\"Otro texto\")<\/pre>\n<\/div>\n<p>Estas llamadas se repetir\u00e1n tantas veces como filas queramos insertar en el TreeView. La variable posicion contendr\u00e1 el n\u00famero de fila en la que se insertar\u00e1n estos datos.<\/p>\n<p>En el caso de utilizar un TreeStore en lugar de un ListStore, el m\u00e9todo insert precisar\u00eda de un par\u00e1metro adicional, antes de la posici\u00f3n, para indicar qu\u00e9 elemento (referenciado mediante un TreeIter) es el padre. Si se pone None, se supondr\u00e1 que cuelga del padre.<\/p>\n<p>Con \u00e9sto ya tenemos nuestro TreeView listo, pero a\u00fan nos faltan dos cosas: borrarlo para meter nuevas filas, y saber qu\u00e9 fila es la que un usuario ha escogido. Lo primero es tan simple como llamar al m\u00e9todo clear del modelo, con lo que podemos volver al \u00faltimo paso (con los set_values) para introducir las nuevas columnas. Para lo segundo s\u00f3lo tenemos que hacer:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">seleccion,iterador = treeview.get_selection().get_selected()<\/pre>\n<\/div>\n<p>Si iterador es None, significa que no hay ninguna fila seleccionada. En caso contrario podemos utilizar<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">seleccion.get_value(iterador,VARIABLE)<\/pre>\n<\/div>\n<p>para obtener el valor de la columna indicada por VARIABLE. Si usamos el valor 1 nos devolver\u00eda el texto de la primera columna; si usamos el valor 2, el color de fondo de la primera columna, y con el valor 3, el texto de la segunda columna. Con el valor 0 nos devolver\u00eda un entero, que hasta ahora no hemos utilizado para nada; pero si a dicho entero le asignamos valores consecutivos al crear las filas, nos dir\u00e1 cual es el n\u00famero de fila que escogi\u00f3 el usuario.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Esta semana tuve que trabajar en serio con el widget GtkTreeView en Python y se me hizo completamente cuesta arriba hasta que, despu\u00e9s de buscar en m\u00faltiples tutoriales y pelearme con el c\u00f3digo, me vino una epifan\u00eda y entend\u00ed su complejo pero potente esquema de funcionamiento; as\u00ed que, en base a la experiencia adquirida, voy &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=20\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">Trabajando con GtkTreeView en Python<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,7],"tags":[],"class_list":["post-20","post","type-post","status-publish","format-standard","hentry","category-programacion","category-tutoriales"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/20","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=20"}],"version-history":[{"count":1,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/20\/revisions"}],"predecessor-version":[{"id":1906,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/20\/revisions\/1906"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=20"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=20"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=20"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}