Este tutorial está cubierto por FDL. Los programas listados aquí estan cubiertos por LGPL.
Freedesktop, también conocido como fdo, es un proyecto software libre iniciado por de uno de los desarrolladores de GNOME, Havoc Pennington, para la estandarización, integración e interoperabilidad de los distintos escritorios.
Freedesktop surgió principalmente como un proyecto entorno al sistema X para la estandarización de los escritorios de Linux con el fin de conseguir que tecnologías existentes estén más integradas, de forma que no haya una total diversidad y separación entre proyectos.
Para ello Freedesktop lo que pretende conseguir es una base de software común para todos los escritorios, englobando tecnologías como las de Mozilla, distintas herramientas gŕaficas como Qt y gtk+, VCL, wine, GNOME, KDE y X Window System.
De este concepto de estandarización nace Cairo
Cairo, intoducida al mundo del Software Libre por Keith Packard, es una biblioteca de gráficos vectoriales en 2D, diseñada para proporcionar imagenes con alta calidad incluídos en el sistema X, OpenGL, buffers de imagen en la memoria y archivos de imagen.
Cairo se diseñó para producir una salida idéntica en todos los dispositivos de salida, mientras que aprovecha la aceleración del hardware cuando este disponible disponible.
Lo que pretende es ofrecer un renderizado independiente de la plataforma, rápido y flexible.
Antes que nada debemos de saber cómo se va a crear la interface gráfica, y está la realizaremos con el diseñador de interfaces de Gnome Glade. Primero lanzamos nuestro diseñador de interfaces
[eric@localhost]glade-2
Lo primero que veremos es la ventana principal de Glade, en ella crearemos un nuevo proyecto ya sea GTK o Gnome.
Posteriormente empezaremos a diseñar la interface, glade nos mostrará diferentes barras, entre ellas la paleta de widgets que es la siguiente.
Esta paleta nos muestra los diferentes widgets y diálogos de Gtk y Gnome. Seleccionaremos el widget de ventana para empezar a crear nuestra interface, este elemento nos crea un nueva ventana en la cuál podremos seguir insertando widgets.
Ahora, para continuar insertando elementos de una manera ordenada y limpia seleccionaremos el widget de tabla y la insertaremos, le asignaremos 2 filas.En la primera fila insertaremos un drawingarea, está sera nuestra area para dibujar, y en la siguiente fila un botón, le podemos asignar un ícono y nombre en la caja de propiedades que veremos más adelante.
Hasta este momento tenemos creada la interface, pero a cada widgets que insertamos le vamos a añadir señales, estas señales nos servirán para poder manejar nuestros gidgets directamente con python. Podemos seleccionar los widgets desde el árbol de widgets.
Proseguiremos a añadir las señales, tenemos una caja que nos miestra las propiedades de los widgets, en ésta podemos modificar sus atributos, así como tamaño, nombre, señales entre otras, nosotros nos enfocaremos en señales.
Primero seleccionamos en nuestro árbol de widgets la ventana, a la cuál le agregaremos una señal de 'destroy' y en el manejador seleccionaremos 'gtk_main_quit', y presionaremos añadir, esto servirá para que cuando cerremos nuestra ventana esta se destruya. Después seleccionamos el widget de drawingarea y seleccionaremos la señal de 'expose_event' y en el manejador podemos escribir 'on_expose' y lo añadimos, por último resta el button, seleccionaremos la señal de 'clicked' y el manejador añadiremos 'gtk_main_quit' esto para que al presionarlo la venta se cierre. Después de esto ya tendremos creada nuestra interface base para todos nuestros programas.
En este ejemplo veremos la potencia de Cairo para dibujar curvas y líneas con python.
#!/usr/bin/env python # -*- coding:UTF-8 -*- from SimpleGladeApp import SimpleGladeApp import gtk import cairo import cairo.gtk class Cairo7GladeApp(SimpleGladeApp): def on_expose_event(self, area, event): self.ctx = cairo.Context() cairo.gtk.set_target_drawable(self.ctx, self.drawingarea1.window) width, height = self.drawingarea1.window.get_size() self.ctx.scale(width/100.0, height/100.0) self.ctx.set_rgb_color(1, 1, 1) self.ctx.rectangle(0, 0, width, height) self.ctx.fill() self.ctx.translate(-0.5, 0) self.draw_curve() self.draw_lines() def draw_curve(self): self.ctx.move_to(10, 50) self.ctx.curve_to(40, 90, 60, 10, 90, 50) self.ctx.set_rgb_color(0,0,0) self.ctx.set_line_width(3) self.ctx.stroke() def draw_lines(self): self.ctx.move_to(10, 50) self.ctx.line_to(40, 90) self.ctx.move_to(60, 10) self.ctx.line_to(90, 50) self.ctx.set_alpha(0.6) self.ctx.set_rgb_color(1, 0.2, 0.2) self.ctx.stroke() app = Cairo7GladeApp('Cairo7GladeApp.glade') app.run()
Para correr utilizar las bibliotecas de cairo en python debes instalar el paquete de python-cairo. Ahora le daremos permisos de ejecución al archivo .py de python
[crac@localhost Cairo7GladeApp]$chmod u+x Cairo7GladeApp.py
[crac@localhost Cairo7GladeApp]./Cairo7GladeApp.py
Ahora veremos como realizar un polígono con un texto animado.
#!/usr/bin/env python # -*- coding UTF-8 -*- from SimpleGladeApp import SimpleGladeApp import gtk import cairo import cairo.gtk import time #import math class CairoGladeApp(SimpleGladeApp): def new(self): self.label = "STOP!" self.count = 0 gtk.timeout_add(500, self.on_timeout) def on_timeout(self): self.count += 1 if self.count > len(self.label): self.count = 0 self.window1.queue_draw() return True def on_expose_event(self, area, event): self.ctx = cairo.Context() cairo.gtk.set_target_drawable(self.ctx, self.drawingarea1.window) width, height = self.drawingarea1.window.get_size() size = min(width, height) self.ctx.scale(width, height) self.ctx.set_alpha(0.75) self.ctx.set_rgb_color(1, 1, 1) self.ctx.rectangle(0, 0, 1, 1) self.ctx.fill() self.draw_polygon() self.draw_text() self.draw_tube() def draw_polygon(self): self.ctx.translate(0.1875, -0.15) self.ctx.move_to(0.1875, 0.1875) self.ctx.rel_line_to(0.25, 0) self.ctx.rel_line_to(0.1875, 0.1875) self.ctx.rel_line_to(0, 0.25) self.ctx.rel_line_to(-0.1875, 0.1875) self.ctx.rel_line_to(-0.25, 0) self.ctx.rel_line_to(-0.1875, -0.1875) self.ctx.rel_line_to(0, -0.25) self.ctx.close_path() self.ctx.save() self.ctx.set_rgb_color(0, 0, 0) self.ctx.set_line_width(0.005) self.ctx.set_line_join(cairo.LINE_JOIN_BEVEL) self.ctx.stroke() self.ctx.restore() self.ctx.set_rgb_color(1, 0, 0) self.ctx.fill() def draw_text(self): self.ctx.save() self.ctx.move_to(0.05, 0.55) self.ctx.set_rgb_color(0, 0, 0) self.ctx.select_font("babelfish") self.ctx.scale_font(0.27) self.ctx.show_text(self.label[0:self.count]) self.ctx.stroke() self.ctx.restore() def draw_tube(self): self.ctx.move_to(0.25, 0.815) self.ctx.rel_line_to(0, 0.3) self.ctx.rel_line_to(0.125, 0) self.ctx.rel_line_to(0, -0.3) self.ctx.set_rgb_color(0.2, 0.1, 0.3) self.ctx.close_path() self.ctx.save() self.ctx.set_rgb_color(0, 0, 0) self.ctx.set_line_width(0.005) self.ctx.stroke() self.ctx.restore() self.ctx.fill() app = CairoGladeApp("CairoGladeApp.glade") app.run()
Este ejemplo nos muestra como utilizar los segmentos de línea formnado un cubo, así como utilizar translucencias.
#!/usr/bin/env python # -*- coding UTF-8 -*- from SimpleGladeApp import SimpleGladeApp import gtk import cairo import cairo.gtk class Cairo4GladeApp(SimpleGladeApp): def new(self): self.elapsed = 95 self.count = 0 self.on_timeout() def on_timeout(self): gtk.timeout_add(self.elapsed, self.on_timeout) self.count += 0.01 if self.count > 1: self.count = 0 self.drawingarea1.queue_draw() def on_expose_event(self, area, event): self.ctx = cairo.Context() cairo.gtk.set_target_drawable(self.ctx, self.drawingarea1.window) width, height = self.drawingarea1.window.get_size() self.ctx.scale(width/100.0, height/100.0) self.ctx.set_rgb_color(0,0,0) self.ctx.rectangle(0, 0, width, height) self.ctx.fill() self.draw_rectangle1() self.draw_rectangle4() self.draw_rectangle2() self.draw_rectangle3() def draw_rectangle1(self): self.ctx.set_line_width(0.3) self.ctx.set_rgb_color(1, 1, 1) self.ctx.rectangle(27, 27, 30, 30) self.ctx.save() self.ctx.set_alpha(self.count) self.ctx.set_rgb_color(0.4, 0.7, 0.9) self.ctx.fill() self.ctx.restore() self.ctx.stroke() def draw_rectangle2(self): self.ctx.rectangle(39, 39, 30, 30) self.ctx.save() self.ctx.set_alpha(self.count) self.ctx.set_rgb_color(0.3, 0.1, 0.2) self.ctx.fill() self.ctx.restore() self.ctx.stroke() def draw_rectangle3(self): self.ctx.set_line_width(0.2) self.ctx.move_to(27, 27) self.ctx.rel_line_to(30, 0) self.ctx.rel_line_to(12, 12) self.ctx.rel_line_to(-30, 0) self.ctx.close_path() self.ctx.save() self.ctx.set_alpha(self.count) self.ctx.set_rgb_color(0.8, 0.4, 0.5) self.ctx.fill() self.ctx.restore() self.ctx.stroke() def draw_rectangle4(self): self.ctx.move_to(27, 57) self.ctx.rel_line_to(30, 0) self.ctx.rel_line_to(12, 12) self.ctx.rel_line_to(-30, 0) self.ctx.close_path() self.ctx.save() self.ctx.set_alpha(self.count) self.ctx.set_rgb_color(0.2, 0.4, 0.2) self.ctx.fill() self.ctx.restore() self.ctx.stroke() app = Cairo4GladeApp('cairo4gladeapp.glade') app.run()