En la nueva versión de DeVeDe (que espero sacar en un par de días) he tenido que trabajar con Cairo para poder generar menús para el disco. La información la saqué de este tutorial sobre PyCairo (en inglés), en donde viene mucha información interesante. Sin embargo, faltaba un detalle importante: como mostrar el dibujo hecho en cairo en una ventana GTK.
En efecto, esto era fundamental porque el usuario tiene que poder ver el resultado final del menú antes de generar el disco (para, por ejemplo, asegurarse de que los títulos no son demasiado largos), y para eso necesito pintarlo en una ventana y no sólo volcarlo a un PNG en disco. Después de mucho buscar y de hacer varias pruebas encontré por fin como hacerlo.
Lo primero es crear un widget GtkDrawingArea, en el que mostraremos el dibujo generado con Cairo, y crear un callback para el evento expose-event. Este evento se produce cada vez que hay que redibujar la ventana (bien porque estaba tapada por otra y la hemos destapado, bien porque estaba minimizada y la hemos maximizado…). En dicho callback será donde hagamos el pintado. Para ello, lo primero que tenemos que hacer es conseguir un contexto de Cairo para dicho widget. Así, si el widget se llama MiDibujo, y arbol es el objeto Glade con nuestras ventanas, haríamos:
# asignamos el callback a nuestra funcion de repintado w=arbol.get_widget("MiDibujo") w.connect("expose-event",repintado) # y definimos el callback. Tiene dos argumentos def repintado(dwidget,evento): cr=dwidget.window.cairo_create() [funciones y métodos de Cairo para pintar]
Y ya podremos usar ese contexto para pintar y trazar todo lo que queramos.
Sin embargo, si el dibujo es estático no tiene sentido que lo tracemos una y otra vez cada vez que se produzca un evento, porque desperdiciamos tiempo de proceso. Lo mejor es tenerlo pintado desde el principio y limitarnos a copiar el bitmapa final en el callback de repintado. Para ello sólo tenemos que crear primero una superficie de Cairo y obtener un contexto para ella:
sf=cairo.ImageSurface(cairo.FORMAT_ARGB32,ResX,Resy) cr1=cairo.Context(sf)
Ahora pintaremos nuestro dibujo en dicha superficie con ese contexto, y una vez que hayamos terminado, almacenaremos el objeto superficie de alguna manera que nos permita acceder a él desde nuestro callback (una variable global es la solución más rápida y menos elegante). Allí sólo tenemos que usar los métodos set_source_surface y paint para transferir la superficie a nuestro widget GtkDrawingArea, ahorrando mucho tiempo de proceso.
def repintado(dwidget,evento): cr=dwidget.window.cairo_create() # sf es la que pintamos en el paso anterior cr.set_source_surface(sf) # transferimos la superficie con el dibujo al Widget cr.paint()
Este truco nos permite también pegar cualquier imagen en la superficie en la que estamos trabajando, e incluso redimensionarla en el proceso. Un ejemplo: queremos crear una imagen de tamaño X,Y, usando como fondo un PNG de tamaño cualquiera, pero de manera que éste se expanda o encoja para ocupar exactamente la superficie de nuestra imagen final. Sólo tendríamos que hacer:
sf_base= cairo.ImageSurface.create_from_png("imagen.png") sf_final=cairo.ImageSurface(cairo.FORMAT_ARGB32,X,Y) # creamos un contexto para pintar cr_final=cairo.Context(sf_final) # cogemos el ancho y alto de la imagen. # Importante: en coma flotante xbase=float(sf_base.get_width()) ybase=float(sf_base.get_height()) # aplicamos el escalado para que la imagen de fondo # pase a tener el mismo tamaño que la imagen final cr_final.scale(float(X)/xbase,float(Y)/ybase) # y estampamos la imagen de origen en la superficie final cr_final.set_source_surface(sf_base) cr_final.paint() # podemos usar el método identity para #restaurar la escala a 1:1 cr.identity_matrix()
Trabajando con PyCairo y GTK por A cuadros está licenciado bajo una Licencia Creative Commons Atribución-CompartirIgual 4.0 Internacional.
Me gustaria saber como se hace para que luego de ejecutar el signal handler de la seleccion de items, el treeview continue mostrandolos como seleccionados.
En mi caso sucede que una vez que pico el boton derecho la seleccion se rompe.
Saludos
JC
Deduzco que quieres usar un treeview y un menú contextual en él… así que lo pongo en el otro artículo.
Que tal:
Primero dejame felicitarte por tan excelente programa como lo es el DeVeDe.
Te pido disculpas de antemano porque creo que este no es el sitio indicado para hacer esta solicitud, sin embargo aqui va. Soy una nulidad en programacion, a pesar de haber hecho algunos esfuerzos en ese sentido siempre quedo en blanco. Seria posible agregar la opcion de poder escoger el color del subtitulo?. Por ejemplo en vez de que queden simplemente en color blanco, digamos que quedaran en color amarillo?
Muchos Saludos
Roberto de Diego
No es posible escoger el color de los subtítulos porque SPUMUX no lo permite 🙁
Entiendo, sabes algo? hay veces en que el subtitulo esta en formato .sub y SPUMUX, como decimos por aca, «se tildea» y lanza un error…no se si habras tenido oportunidad de ver algo como eso…
Puede ser porque haya alguna frase demasiado grande y SPUMUX no es capaz de meterla en una sola línea… Una solución es reducir el tamaño de los subtítulos… a ver si tengo un rato y lo añado.