<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8895950188245720481</atom:id><lastBuildDate>Fri, 08 Nov 2024 15:14:54 +0000</lastBuildDate><category>Linux</category><category>ReportLab</category><category>python</category><category>Informática</category><category>Kubuntu</category><category>platypus</category><category>Ubuntu</category><category>VirtualBox</category><category>Chakra</category><category>Windows</category><category>canvas</category><category>virtualización</category><category>Mac OS Tigger</category><category>Sublime Text</category><category>gtk</category><category>64 Bits</category><category>Firefox 4</category><category>Instalación</category><category>Mandriva</category><category>PDF</category><category>Tres sistemas operativos en uno</category><category>Tuneadores</category><category>Tweetdeck</category><category>cuatro sistemas operativos en uno</category><category>varios sistemas operativos en uno</category><category>Bateria</category><category>Editores</category><category>Gmail</category><category>Google Apps</category><category>Kde</category><category>Kmail</category><category>Kopete</category><category>Kwallet</category><category>Mac Os Leopard</category><category>Mouse</category><category>Redes</category><category>Salud Informática</category><category>Satellite L655</category><category>Síndrome</category><category>Windows 7</category><category>cairo</category><category>choqok</category><category>css</category><category>flowable</category><category>glade</category><category>gnome</category><category>ipcalc</category><category>microblogging</category><category>py2exe</category><category>subneteo</category><category>threads</category><title>Mente Leal</title><description>Bits de ideas en un solo lugar</description><link>http://menteleal.blogspot.com/</link><managingEditor>noreply@blogger.com (Anonymous)</managingEditor><generator>Blogger</generator><openSearch:totalResults>55</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-5688215207167190596</guid><pubDate>Wed, 06 Jan 2016 15:27:00 +0000</pubDate><atom:updated>2016-01-06T10:27:34.489-05:00</atom:updated><title>Desactivar actualización de un plugin en Wordpress</title><description>&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Vamos a &quot;Plugins - Plugins instalados&quot;,&amp;nbsp;hacemos clic en editar.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Al&amp;nbsp;principio&amp;nbsp;del código ponemos&lt;/span&gt;&lt;span style=&quot;font-family: Tahoma, Verdana, Arial;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
Código PHP:&lt;br /&gt;
?php/**&lt;br /&gt;
* @package admin_flush_w3tc&lt;br /&gt;
* @version 1.2&lt;br /&gt;
*/&lt;br /&gt;
/*&lt;br /&gt;
Plugin Name: Admin Flush W3TC Cache
&lt;/div&gt;
&lt;br /&gt;
Cambiamos la linea donde esta la versión por algo más alto como *&amp;nbsp;@version 999&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://menteleal.blogspot.com/2016/01/desactivar-actualizacion-de-un-plugin.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-5102351902676405575</guid><pubDate>Thu, 24 Apr 2014 15:28:00 +0000</pubDate><atom:updated>2014-04-24T10:29:33.809-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Chakra</category><category domain="http://www.blogger.com/atom/ns#">Sublime Text</category><title>Instalar sublime text en chakra y en otros linux</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkueUEgPJVgsCTYHlo-le_EmoWeBZO9bFwmkKmXWWewh_I3qU1sgZsa0W9SN9XsAxNI7B8VzXF2NgTiouUpIO6T65pGwmhpkFXOneEvai6LOtA0s9hpvuXbXRUbZk_XsJTe0U4f8u3FdI/s1600/instant%C3%A1nea1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkueUEgPJVgsCTYHlo-le_EmoWeBZO9bFwmkKmXWWewh_I3qU1sgZsa0W9SN9XsAxNI7B8VzXF2NgTiouUpIO6T65pGwmhpkFXOneEvai6LOtA0s9hpvuXbXRUbZk_XsJTe0U4f8u3FdI/s1600/instant%C3%A1nea1.png&quot; height=&quot;313&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Primero debemos bajarnos el archivo tar.bz2 de&amp;nbsp;&lt;a href=&quot;http://www.sublimetext.com/&quot;&gt;http://www.sublimetext.com/&lt;/a&gt;&amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Luego debemos descomprimirlo:&lt;br /&gt;
&lt;br /&gt;
Para 32bit:&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
tar -jxvf Sublime\ Text\ 2\ 2.0.1.tar.bz2&lt;/div&gt;
&lt;br /&gt;
Para 64bits:
&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
tar -jxvf Sublime\ Text\ 2\ 2.0.1\ x64.tar.bz2 &lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Luego aplicar los siguientes comandos:&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
sudo mv Sublime\ Text\ 2 sublime&lt;br /&gt;
sudo mv sublime /opt/
cd /opt&lt;br /&gt;
sudo chown -R root:root sublime&lt;br /&gt;
sudo chmod -R +r sublime
&lt;/div&gt;
&lt;br /&gt;
Ahora tenemos que crear los ejecutables:
&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
sudo touch /usr/bin/sublime_text&lt;br /&gt;
sudo chmod 775 /usr/bin/sublime_text
&lt;/div&gt;
&lt;br /&gt;
Tenemos que editar algunos archivos:
&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
sudo nano /usr/bin/sublime_text&lt;/div&gt;
&lt;br /&gt;
y le agregamos lo siguiente:
&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
#!/bin/sh&lt;br /&gt;
#export MOZILLA_FIVE_HOME=&quot;/usr/lib/mozilla/&quot;&lt;br /&gt;
export SUBLIME_HOME=&quot;/opt/sublime&quot;&lt;br /&gt;
$SUBLIME_HOME/sublime_text &quot;$*
&lt;/div&gt;
&lt;br /&gt;
grabamos con Ctrl + o y cerramos con Ctrl + x.&lt;br /&gt;
&lt;br /&gt;
Editamos este otro archivo:&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
sudo nano /usr/share/applications/sublime.desktop
&lt;/div&gt;
&lt;br /&gt;
y le agregamos el siguiente contenido:
&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
[Desktop Entry]&lt;br /&gt;
Encoding=UTF-8&lt;br /&gt;
Name=Sublime Text&lt;br /&gt;
Comment=Sublime Text 2&lt;br /&gt;
Exec=sublime_text&lt;br /&gt;
Icon=/opt/sublime/Icon/256x256/sublime_text.png&lt;br /&gt;
Terminal=false&lt;br /&gt;
Type=Application&lt;br /&gt;
Categories=GNOME;GTK;Utility;TextEditor;&lt;br /&gt;
StartupNotify=true
&lt;/div&gt;
&lt;br /&gt;
De igual forma, lo grabamos y cerramos.
Ya podemos visualizarlo en nuestro lanzador. En el caso de chakra se encontrará en Utilidades.

</description><link>http://menteleal.blogspot.com/2014/04/instalar-sublime-text-en-chakra-y-en.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkueUEgPJVgsCTYHlo-le_EmoWeBZO9bFwmkKmXWWewh_I3qU1sgZsa0W9SN9XsAxNI7B8VzXF2NgTiouUpIO6T65pGwmhpkFXOneEvai6LOtA0s9hpvuXbXRUbZk_XsJTe0U4f8u3FdI/s72-c/instant%C3%A1nea1.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-7028648135052248867</guid><pubDate>Wed, 19 Feb 2014 22:57:00 +0000</pubDate><atom:updated>2014-02-19T17:57:56.523-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Gráficos (16)</title><description>Está es la última parte de ReportLab, y pueden usarlo, como muchos, con &lt;b&gt;Django&lt;/b&gt;. Yo lo uso más en aplicaciones de escritorio, pero donde este Python, ReportLab es una manera fácil de trabajar con pdf.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por si necesitan alguna función bastante rebuscada, pueden acceder al REFERENCE de ReportLab.&lt;br /&gt;
&lt;br /&gt;
Bien, en cuanto a gráficos, podemos decir que es un subpaquete de ReportLab integrado a este,&amp;nbsp; veamos como se trabaja con ellos:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwxSMIh1-QnkSIRse_1PflZNl9IOaBYgSCEEsPGf2KPpU1_ViPNxlvheWGgZ9aRAHf0lRQHbtlK_YQ3m_Q3m9ejYr38ixMelqPV-QELvp-309dFIVx6nJ9JD5GJrbDlYG-HJt7KJw5N1I/s1600/Screenshot_1.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwxSMIh1-QnkSIRse_1PflZNl9IOaBYgSCEEsPGf2KPpU1_ViPNxlvheWGgZ9aRAHf0lRQHbtlK_YQ3m_Q3m9ejYr38ixMelqPV-QELvp-309dFIVx6nJ9JD5GJrbDlYG-HJt7KJw5N1I/s320/Screenshot_1.png&quot; height=&quot;241&quot; width=&quot;400&quot; /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;# -*- coding:utf-8 -*-
import os

from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, PageBreak
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import A4
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
from reportlab.lib import colors
from reportlab.lib.units import inch

from reportlab.graphics.shapes import Drawing, Rect, String, Group, Line
from reportlab.graphics.widgets.markers import makeMarker


doc = SimpleDocTemplate(&#39;test.pdf&#39;, pagesize=A4)
story = []
estilo = getSampleStyleSheet()

#EJEMPLO 01: Dibujando alguna forma y texto
#==========
d = Drawing(400, 200)

r =(Rect(50, 50, 300, 100, fillColor=colors.yellow))
r.strokeColor = colors.red  # otra forma de agregar propiedades
r.strokeWidth = 3
d.add(r)

d.add(String(150,100, &#39;Hola mundo&#39;, fontSize=18, fillColor=colors.red))
d.add(String(180,86, &#39;Caracteres especiales: \
             \xc2\xa2\xc2\xa9\xc2\xae\xc2\xa3\xce\xb1\xce\xb2&#39;,
             fillColor=colors.red))
story.append(d)
#Entre las distintas formas tenemos: Rect, Circle, Ellipse, Wedge, Polygon,
#Line, PolyLine, String, Group, 


#EJEMPLO 02: Obteniendo propiedades
#==========
#Esto es un buena forma de saber las propiedades de los elementos que usemos,
#usaremos pprint que nos lo mostrará en el shell
import pprint
r = Rect(0, 0, 200, 100)
pprint.pprint(r.getProperties())

#EJEMPLO 03: Label
#==========
from reportlab.graphics.charts.textlabels import Label

d = Drawing(200, 100)
lab = Label()
lab.setOrigin(100,90)
lab.angle = 45
lab.dx = 0  # desplazamiento en x
lab.dy = -20  # desplazamiento en y
lab.boxStrokeColor = colors.green
lab.setText(&#39;Un \nLabel \nMulti-Linea&#39;)
d.add(lab)
pprint.pprint(lab.getProperties())  # tiene muchas más propiedades
story.append(d)

#EJEMPLO 04: Ejes
#===========
#Nota: Aquí los datos aún no se muestran
from reportlab.graphics.charts.axes import XCategoryAxis,YValueAxis
d = Drawing(400, 200)
data = [(10, 20, 30, 40), (15, 22, 37, 42)]

xAxis = XCategoryAxis()
xAxis.setPosition(75, 75, 300)  # x, y, ancho
xAxis.configure(data)
xAxis.categoryNames = [&#39;Oso&#39;, &#39;Tigre&#39;, &#39;León&#39;, &#39;Camaleón&#39;]
xAxis.labels[2].dy = -15
xAxis.labels[2].angle = 30
xAxis.labels[2].fontName = &#39;Times-Bold&#39;

yAxis = YValueAxis()
yAxis.setPosition(50, 80, 125)
yAxis.configure(data)
d.add(xAxis)
d.add(yAxis)

story.append(d)
story.append(PageBreak())

#EJEMPLO 05: Gráfico de Barras
#===========
from reportlab.graphics.charts.barcharts import VerticalBarChart

d = Drawing(400, 200)
data = [
        (13, 5, 20, 22, 37, 45, 19, 4),
        (14, 6, 21, 23, 38, 46, 20, 5)
        ]
bc = VerticalBarChart()
bc.x = 50
bc.y = 50
bc.height = 125
bc.width = 300
bc.data = data
bc.strokeColor = colors.black
bc.valueAxis.valueMin = 0
bc.valueAxis.valueMax = 50
bc.valueAxis.valueStep = 10  #paso de distancia entre punto y punto
bc.categoryAxis.labels.boxAnchor = &#39;ne&#39;
bc.categoryAxis.labels.dx = 8
bc.categoryAxis.labels.dy = -2
bc.categoryAxis.labels.angle = 30
bc.categoryAxis.categoryNames = [&#39;Ene-14&#39;,&#39;Feb-14&#39;,&#39;Mar-14&#39;,
       &#39;Abr-14&#39;,&#39;May-14&#39;,&#39;Jun-14&#39;,&#39;Jul-14&#39;,&#39;Ago-14&#39;]
bc.groupSpacing = 10
bc.barSpacing = 2
#bc.categoryAxis.style = &#39;stacked&#39;  # Una variación del gráfico
d.add(bc)
pprint.pprint(bc.getProperties())
story.append(d)

#EJEMPLO 06: Gráfico linear
#==========
from reportlab.graphics.charts.linecharts import HorizontalLineChart

titulo = Paragraph(&quot;Calificaciones Informática&quot;, estilo[&#39;title&#39;])
story.append(titulo)
story.append(Spacer(0, inch*.1))

d = Drawing(400, 200)
lc = HorizontalLineChart()
lc.x = 30
lc.y = 50
lc.height = 125
lc.width = 350
lc.data = [[8,10,5,2]]
lc.categoryAxis.categoryNames = [&#39;Suspenso&#39;, &#39;Aprobado&#39;, &#39;Notable&#39;, 
                                &#39;Sobresaliente&#39;]
lc.categoryAxis.labels.boxAnchor = &#39;n&#39;
lc.valueAxis.valueMin = 0
lc.valueAxis.valueMax = 12
lc.valueAxis.valueStep = 2  # Los pasos pueden ser tambien [10, 15, 30, 35, 40]
lc.lines[0].strokeWidth = 2
lc.lines[0].symbol = makeMarker(&#39;FilledCircle&#39;) # círculos rellenos
lc.lines[1].strokeWidth = 1.5
d.add(lc)
story.append(d)

#EJEMPLO 07: Trazos lineales
#==========
from reportlab.graphics.charts.lineplots import LinePlot

d = Drawing(400, 200)
data = [
    ((1,1), (2,2), (2.5,1), (3,3), (4,6)),
    ((1,2), (2,3), (2.5,2), (3.5,5), (4,3))
]
lp = LinePlot()
lp.x = 50
lp.y = 50
lp.height = 125
lp.width = 300
lp.data = data
lp.joinedLines = 1
lp.fillColor = colors.yellow
lp.lines[0].symbol = makeMarker(&#39;FilledCircle&#39;)
lp.lines[1].symbol = makeMarker(&#39;Circle&#39;)
lp.lineLabelFormat = &#39;%2.0f&#39;
lp.strokeColor = colors.black
lp.xValueAxis.valueMin = 0
lp.xValueAxis.valueMax = 5
lp.xValueAxis.valueSteps = [1, 2, 2.5, 3, 4, 5]
lp.xValueAxis.labelTextFormat = &#39;%2.1f&#39;
lp.yValueAxis.valueMin = 0
lp.yValueAxis.valueMax = 7
lp.yValueAxis.valueSteps = [1, 2, 3, 5, 6]


#Veamos como se inserta las leyendas. En este caso usaremos el LineLegend,
#que son leyendas en linea.
from reportlab.graphics.charts.legends import LineLegend

legend = LineLegend()
legend.fontSize = 8
legend.alignment = &#39;right&#39;
legend.x = 0
legend.y = 0
legend.columnMaximum = 2
legend.fontName  = &#39;Helvetica&#39;

#Definimos nuestras etiquetas  y usamos los colores del propio gráfico.
etiquetas  = [&#39;Opcion 01&#39;, &#39;Opcion 02&#39;]
legend.colorNamePairs  = [(lp.lines[i].strokeColor, etiquetas[i]) 
                            for i in xrange(len(lp.data))]

d.add(lp)
d.add(legend)
story.append(d)


#EJEMPLO 08: Gráficos Circulares
#==========
from reportlab.graphics.charts.piecharts import Pie

d = Drawing(300, 200)
pc = Pie()
pc.x = 65
pc.y = 15
pc.width = 170
pc.height = 170
pc.data = [10,20,30,40,50]
pc.labels = [&#39;IE&#39;,&#39;Kopete&#39;,&#39;Chrome&#39;,&#39;Firefox&#39;,&#39;Opera&#39;]

pc.slices.strokeWidth=0.5
pc.slices[3].popout = 10
pc.slices[3].strokeWidth = 2
pc.slices[3].strokeDashArray = [2,2]
pc.slices[3].labelRadius = 1.75
pc.slices[3].fontColor = colors.red
pc.sideLabels = 1  # Con 0 no se muestran líneas hacia las etiquetas
#~ pc.slices.labelRadius = 0.65  # Para mostrar el texto dentro de las tajadas

#Insertamos la legenda

from reportlab.graphics.charts.legends import Legend
legend = Legend() 
legend.x               = 370 
legend.y               = 0 
legend.dx              = 8  
legend.dy              = 8  
legend.fontName        = &#39;Helvetica&#39;  
legend.fontSize        = 7  
legend.boxAnchor       = &#39;n&#39;  
legend.columnMaximum   = 10  
legend.strokeWidth     = 1  
legend.strokeColor     = colors.black  
legend.deltax          = 75  
legend.deltay          = 10  
legend.autoXPadding    = 5  
legend.yGap            = 0  
legend.dxTextSpace     = 5  
legend.alignment       = &#39;right&#39;  
legend.dividerLines    = 1|2|4  
legend.dividerOffsY    = 4.5  
legend.subCols.rpad    = 30  

#Insertemos nuestros propios colores
colores  = [colors.blue, colors.red, colors.green, colors.yellow, colors.pink]
for i, color in enumerate(colores): 
    pc.slices[i].fillColor = color
    
legend.colorNamePairs  = [(
                            pc.slices[i].fillColor, 
                            (pc.labels[i][0:20], &#39;%0.2f&#39; % pc.data[i])
                           ) for i in xrange(len(pc.data))]

d.add(pc) 
d.add(legend)
story.append(d)

#EJEMPLO 09: Usando Grupo
#==========
d = Drawing(400, 200)
Ejes = Group(
    Line(0,0,100,0),  # eje x
    Line(0,0,0,50),   # eje y
    Line(0,10,10,10), # Marcas en el eje y
    Line(0,20,10,20),
    Line(0,30,10,30),
    Line(0,40,10,40),
    Line(10,0,10,10), # Marcas en el eje x
    Line(20,0,20,10),
    Line(30,0,30,10),
    Line(40,0,40,10),
    Line(50,0,50,10),
    Line(60,0,60,10),
    Line(70,0,70,10),
    Line(80,0,80,10),
    Line(90,0,90,10),
    String(20, 35, &#39;Ejes&#39;, fill=colors.black)
    )

PrimerGrupoEjes = Group(Ejes)
PrimerGrupoEjes.translate(10,10)
d.add(PrimerGrupoEjes)

SegundoGrupoEjes = Group(Ejes)
SegundoGrupoEjes.translate(150,10)
SegundoGrupoEjes.rotate(15)
d.add(SegundoGrupoEjes)

TercerGrupoEjes = Group(Ejes)
TercerGrupoEjes.translate(300,10)
TercerGrupoEjes.rotate(30)
d.add(TercerGrupoEjes)

story.append(d)

doc.build(story)
os.system(&#39;test.pdf&#39;)

&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-graficos-16.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwxSMIh1-QnkSIRse_1PflZNl9IOaBYgSCEEsPGf2KPpU1_ViPNxlvheWGgZ9aRAHf0lRQHbtlK_YQ3m_Q3m9ejYr38ixMelqPV-QELvp-309dFIVx6nJ9JD5GJrbDlYG-HJt7KJw5N1I/s72-c/Screenshot_1.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-4334067147335544799</guid><pubDate>Tue, 18 Feb 2014 22:43:00 +0000</pubDate><atom:updated>2014-02-18T17:43:21.048-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">platypus</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Platypus -  Sobre las tablas (15)</title><description>Las tablas trabajan con un mecanismo de grilla, se ajustan al contenido. Entre sus argumentos principales tenemos: &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Table(data, colWidths=None, rowHeights=None, style=None&lt;/b&gt;&lt;b&gt;)&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
La &lt;b&gt;data &lt;/b&gt;debe ser texto, instancias de Flowables, una lista o una tupla. &lt;b&gt;colWidths &lt;/b&gt;es el ancho de las columnas, asi como el alto sería &lt;b&gt;rowHeights&lt;/b&gt;. Para poner los estilos se puede usar el método &lt;b&gt;setStyle&lt;/b&gt;. Además tenemos &lt;b&gt;TableSyle&lt;/b&gt;, como veremos su uso en el ejemplo, pero sea cuál sea el método que usemos, los argumentos disponibles son:&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
FONT&lt;br /&gt;
FONTNAME or FACE&lt;br /&gt;
FONTSIZE or SIZE&lt;br /&gt;
LEADING&lt;br /&gt;
TEXTCOLOR&lt;br /&gt;
ALIGN or ALIGNMENT&lt;br /&gt;
LEFTPADDING&lt;br /&gt;
RIGHTPADDING&lt;br /&gt;
BOTTOMPADDING&lt;br /&gt;
TOPPADDING&lt;br /&gt;
BACKGROUND&lt;br /&gt;
ROWBACKGROUNDS&amp;nbsp; Son una lista de colores ciclico por ejemplo: (color1, color2)&lt;br /&gt;
COLBACKGROUNDS&lt;br /&gt;
VALIGN&amp;nbsp; Puede ser TOP, MIDDLE o BOTTOM&lt;br /&gt;
INNERGRID&amp;nbsp; Linea dentro del grid&lt;br /&gt;
BOX&amp;nbsp; Lineas alrededor del grid&lt;br /&gt;
GRID&amp;nbsp; Combinación de box e innergrid&lt;br /&gt;
LINEBELOW&amp;nbsp; Linea arriba&lt;br /&gt;
LINEABOVE&amp;nbsp; Linea abajo&lt;br /&gt;
LINEBEFORE&amp;nbsp; Línea antes Ej: (&#39;LINEBEFORE&#39;,(2,1),(2,-2),1,colors.pink)&lt;br /&gt;
LINEAFTER&amp;nbsp; Línea posterior&lt;br /&gt;
SPAN&amp;nbsp; Combinar celdas&lt;br /&gt;
&lt;br /&gt;
Veamos el ejemplo, en el que mostramos las distintas propiedas, incluyendo combinación de celdas e insersión de párrafos e imágenes.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiI4rrpGcoAPh9c17YGY1d9UJiEXDMDLke8WQgD5TF7-sJF84rO7zFJ6gxh4g0MLm_5MFscZ2wRpOzloKbUgPrCtreyMtcZF4FejVU2c_1riQ07qeLaU_YlL0zpGfvy0Uy6qxla93pnPw/s1600/Screenshot_10.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiI4rrpGcoAPh9c17YGY1d9UJiEXDMDLke8WQgD5TF7-sJF84rO7zFJ6gxh4g0MLm_5MFscZ2wRpOzloKbUgPrCtreyMtcZF4FejVU2c_1riQ07qeLaU_YlL0zpGfvy0Uy6qxla93pnPw/s1600/Screenshot_10.png&quot; height=&quot;335&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: py;&quot;&gt;import os
#Librerias reportlab a usar:
from reportlab.platypus import (SimpleDocTemplate, PageBreak, Image, Spacer,
Paragraph, Table, TableStyle)
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors

doc = SimpleDocTemplate(&quot;test.pdf&quot;, pagesize = A4)
story=[]

#Ejemplo 01
t = Table([
        [&#39;&#39;, &#39;Ventas&#39;, &#39;Compras&#39;], 
        [&#39;Enero&#39;, 1000, 2000], 
        [&#39;Febrero&#39;, 3000, 100.5],
        [&#39;Marzo&#39;, 2000, 1000],
        [&#39;Abril&#39;, 1500, 1500]
    ], colWidths=80, rowHeights=30)
t.setStyle([
        (&#39;TEXTCOLOR&#39;, (0, 1), (0, -1), colors.blue),
        (&#39;TEXTCOLOR&#39;, (1, 1), (2, -1), colors.green),
        (&#39;BACKGROUND&#39;,(1,1),(-1,-1),colors.cyan),
        (&#39;BOX&#39;,(1,1),(-1,-1),1.25,colors.yellow),
        (&#39;INNERGRID&#39;,(1,1),(-1,-1),1,colors.red),
        (&#39;VALIGN&#39;, (0,0), (-1, -1), &#39;MIDDLE&#39;),
    ])
story.append(t)
story.append(Spacer(0,15))

#Ejemplo02
datos = (
        (&#39;Nombre ciclo&#39;, &#39;Núm. Alumnos&#39;, &#39;Núm aprobados&#39;),
        (&#39;Desarrollo Aplic. Informáticas&#39;, 15, 5),
        (&#39;Admin. Sist. Informáticos&#39;, 40, 25),
        (&#39;Explotación Sist. Informáticos&#39;, 50, 20)
    )
tabla = Table(data = datos,
              style = [
                       (&#39;GRID&#39;,(0,0),(-1,-1),0.5,colors.grey),
                       (&#39;BOX&#39;,(0,0),(-1,-1),2,colors.black),
                       (&#39;BACKGROUND&#39;, (0, 0), (-1, 0), colors.pink),
                       ]
              )
story.append(tabla)
story.append(Spacer(0,15))

#Ejemplo 03
estiloTabla = TableStyle([
     (&#39;LINEABOVE&#39;, (0,0), (-1, 0), 2, colors.green),
     (&#39;ALIGN&#39;, (1,1), (-1, -1), &#39;RIGHT&#39;),
     (&#39;ROWBACKGROUNDS&#39;, (0,0), (-1, -1), (colors.yellow, None)),
     
    ])
estiloTabla.add(&#39;BACKGROUND&#39;, (0,0), (-1,0), colors.Color(0, 0.7, 0.7))
t = Table([
        [&#39;&#39;, &#39;Ventas&#39;, &#39;Compras&#39;], 
        [&#39;Enero&#39;, 1000, 2000], 
        [&#39;Febrero&#39;, 3000, 100.5],
        [&#39;Marzo&#39;, 2000, 1000],
        [&#39;Abril&#39;, 1500, 1500]
    ], style = estiloTabla)

#Ejemplo 04: CELDAS COMPLEJAS
estilo = getSampleStyleSheet()
I = Image(&#39;tuxTemplario.png&#39;, width=100, height=100)

P1 = Paragraph(&#39;&#39;&#39;El &lt;b&gt;tux&lt;/b&gt; templario&#39;&#39;&#39;, estilo[&quot;BodyText&quot;])
P2 = Paragraph(&#39;&#39;&#39;Viva Linux&#39;&#39;&#39;, estilo[&quot;BodyText&quot;])

t = Table(
    data=[
        [&#39;A&#39;,   &#39;B&#39;, &#39;C&#39;,     P1, &#39;D&#39;],
        [&#39;00&#39;, &#39;01&#39;, &#39;02&#39;, [I,P2], &#39;04&#39;],
        [&#39;10&#39;, &#39;11&#39;, &#39;12&#39;, &#39;13&#39;, &#39;14&#39;],
        [&#39;20&#39;, &#39;21&#39;, &#39;22&#39;,  &#39;23&#39;, &#39;24&#39;],
        [&#39;30&#39;, &#39;31&#39;, &#39;32&#39;,  &#39;33&#39;, &#39;34&#39;]
    ],
    style=[
        (&#39;GRID&#39;,(1,1),(-2,-2),1,colors.green),
        (&#39;BOX&#39;,(0,0),(1,-1),2,colors.red),
        (&#39;LINEABOVE&#39;,(1,2),(-2,2),1,colors.blue),
        (&#39;LINEBEFORE&#39;,(2,1),(2,-2),1,colors.pink),
        (&#39;BACKGROUND&#39;, (0, 0), (0, 1), colors.pink),
        (&#39;BACKGROUND&#39;, (1, 1), (1, 2), colors.lavender),
        (&#39;BACKGROUND&#39;, (2, 2), (2, 3), colors.orange),
        (&#39;BOX&#39;,(0,0),(-1,-1),2,colors.black),
        (&#39;GRID&#39;,(0,0),(-1,-1),0.5,colors.black),
        (&#39;VALIGN&#39;,(3,0),(3,0),&#39;BOTTOM&#39;),
        (&#39;BACKGROUND&#39;,(3,0),(3,0),colors.limegreen),
        (&#39;BACKGROUND&#39;,(3,1),(3,1),colors.khaki),
        (&#39;ALIGN&#39;,(3,1),(3,1),&#39;CENTER&#39;),
        (&#39;BACKGROUND&#39;,(3,2),(3,2),colors.beige),
        (&#39;ALIGN&#39;,(3,2),(3,2),&#39;LEFT&#39;),
    ]
)
story.append(t)

#Ejemplo 05: Combinación de celdas

t=Table(
    data=[
        [&#39;Arriba\nIzquierda&#39;, &#39;&#39;, &#39;02&#39;, &#39;03&#39;, &#39;04&#39;],
        [&#39;&#39;, &#39;&#39;, &#39;12&#39;, &#39;13&#39;, &#39;14&#39;],
        [&#39;20&#39;, &#39;21&#39;, &#39;22&#39;, &#39;Abajo\nDerecha&#39;, &#39;&#39;],
        [&#39;30&#39;, &#39;31&#39;, &#39;32&#39;, &#39;&#39;, &#39;&#39;]
    ],
    style=[
        (&#39;GRID&#39;,(0,0),(-1,-1),0.5,colors.grey),
        (&#39;BACKGROUND&#39;,(0,0),(1,1),colors.palegreen),
        (&#39;SPAN&#39;,(0,0),(1,1)),
        (&#39;BACKGROUND&#39;,(-2,-2),(-1,-1), colors.pink),
        (&#39;SPAN&#39;,(-2,-2),(-1,-1)),
    ])
story.append(Spacer(0, 10))
story.append(t)

doc.build(story)
os.system(&quot;test.pdf&quot;)

&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-platypus-sobre-las-tablas.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiI4rrpGcoAPh9c17YGY1d9UJiEXDMDLke8WQgD5TF7-sJF84rO7zFJ6gxh4g0MLm_5MFscZ2wRpOzloKbUgPrCtreyMtcZF4FejVU2c_1riQ07qeLaU_YlL0zpGfvy0Uy6qxla93pnPw/s72-c/Screenshot_10.png" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-2726872826061235315</guid><pubDate>Mon, 17 Feb 2014 23:35:00 +0000</pubDate><atom:updated>2014-02-17T18:49:54.749-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">platypus</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Platypus - Sobre los párrafos (14)</title><description>&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;Paragraph(text, style, bulletText=None)&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
Evidentemente &lt;b&gt;text &lt;/b&gt;es el texto a escribir. Algo importante y a destacar es que permite el uso de texto Python entre las triples comillas&lt;b&gt; &lt;/b&gt;simples (&#39;&#39;&#39; y &#39;&#39;&#39;). &lt;b&gt;bulletText &lt;/b&gt;provee al texto un punto y aparte por defecto para el párrafo. El tipo de letra y otras propiedades del texto se configuran en el argumento &lt;b&gt;style&lt;/b&gt;, que es una instancia de la clase ParagraphStyle, y que pueden obtenerse y usarse de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
estilo=getSampleStyleSheet()
estilo.add(ParagraphStyle(name = &quot;ejemplo&quot;,  alignment=TA_CENTER, fontSize=20,
           fontName=&quot;Helvetica-BoldOblique&quot;))
&lt;/pre&gt;
&lt;br /&gt;
Los argumentos principales de la clase ParagraphStyle son:&lt;br /&gt;
&lt;br /&gt;
class ParagraphStyle(PropertySet):&lt;br /&gt;
defaults = {&lt;br /&gt;
&#39;fontName&#39;:&#39;Times-Roman&#39;,&amp;nbsp;&lt;b&gt; # Nombre de la fuente&lt;/b&gt;&lt;br /&gt;
&#39;fontSize&#39;:10,&amp;nbsp; &lt;b&gt;# Tamaño de fuente&lt;/b&gt;&lt;br /&gt;
&#39;leading&#39;:12,&amp;nbsp;&lt;b&gt; # Espaciado entre lineas&lt;/b&gt;&lt;br /&gt;
&#39;leftIndent&#39;:0,&amp;nbsp; &lt;b&gt;# Identación a la izquierda&lt;/b&gt;&lt;br /&gt;
&#39;rightIndent&#39;:0,&amp;nbsp; &lt;b&gt;# Identación a la derecha&lt;/b&gt;&lt;br /&gt;
&#39;firstLineIndent&#39;:0,&amp;nbsp; &lt;b&gt;# Primera linea identada&lt;/b&gt;&lt;br /&gt;
&#39;alignment&#39;:TA_LEFT,&amp;nbsp; &lt;b&gt;# Alineación&lt;/b&gt;&lt;br /&gt;
&#39;spaceBefore&#39;:0,&amp;nbsp; &lt;b&gt;# Espacio antes del párrafo (excepto en el top de un frame)&lt;/b&gt;&lt;br /&gt;
&#39;spaceAfter&#39;:0,&amp;nbsp;&lt;b&gt; # Espacio después del párrafo (excepto en botton de un frame)&lt;/b&gt;&lt;br /&gt;
&#39;textColor&#39;: black,&amp;nbsp; &lt;b&gt;# Color de Texto&lt;/b&gt;&lt;br /&gt;
&#39;backColor&#39;:None,&amp;nbsp; &lt;b&gt;# Color de fondo&lt;/b&gt;&lt;br /&gt;
&#39;borderWidth&#39;: 0,&amp;nbsp; &lt;b&gt;# Ancho de borde&lt;/b&gt;&lt;br /&gt;
&#39;borderPadding&#39;: 0,&amp;nbsp; &lt;b&gt;# Padding desde el borde&lt;/b&gt;&lt;br /&gt;
&#39;borderColor&#39;: None,&amp;nbsp;&lt;b&gt; # Color de Borde&lt;/b&gt;&lt;br /&gt;
&#39;borderRadius&#39;: None,&amp;nbsp;&lt;b&gt; # Radio de las intersecciones del borde&lt;/b&gt;&lt;br /&gt;
&#39;bulletFontName&#39;:&#39;Symbol&#39;,&amp;nbsp;&lt;b&gt; # Nombre de la Fuente de la viñeta&lt;/b&gt;&lt;br /&gt;
&#39;bulletFontSize&#39;:10,&amp;nbsp; &lt;b&gt;# Tamaño de la viñeta&lt;/b&gt;&lt;br /&gt;
&#39;bulletIndent&#39;:0,&lt;b&gt;&amp;nbsp; # Identación de la viñeta&lt;/b&gt;&lt;br /&gt;
&amp;nbsp;}&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Veamos un ejemplo en el que se muestra el uso de los atributos de párrafo, así como manejo de etiquetas de marcado XML, inserción de lista númeradas, plantillas de enumeración, viñetas y más. Para ello, &lt;a href=&quot;https://googledrive.com/host/0Bx54icPRBpCYdEhTdGFQZURpZzQ/14%20Platypus%20-%20Parrafos.py&quot;&gt;puedes descargar el ejemplo&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLupTGJlGRlIaZrNhfCvmjkuVjUtx2y_R7h8kuT5hNL09Tqtkz6x58IqOrSWFDRyUSiro7BnXTxe7A3-jKgxRd_wyiNOJKjHxBeIJiLnmJfrjJnG-2QoaRtqy5yOqYuaPh3b7uv5Ye-7k/s1600/Screenshot_9.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLupTGJlGRlIaZrNhfCvmjkuVjUtx2y_R7h8kuT5hNL09Tqtkz6x58IqOrSWFDRyUSiro7BnXTxe7A3-jKgxRd_wyiNOJKjHxBeIJiLnmJfrjJnG-2QoaRtqy5yOqYuaPh3b7uv5Ye-7k/s1600/Screenshot_9.png&quot; height=&quot;265&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;</description><link>http://menteleal.blogspot.com/2014/02/reportlab-platypus-sobre-los-parrafos-14.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLupTGJlGRlIaZrNhfCvmjkuVjUtx2y_R7h8kuT5hNL09Tqtkz6x58IqOrSWFDRyUSiro7BnXTxe7A3-jKgxRd_wyiNOJKjHxBeIJiLnmJfrjJnG-2QoaRtqy5yOqYuaPh3b7uv5Ye-7k/s72-c/Screenshot_9.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-5693617926443731441</guid><pubDate>Mon, 17 Feb 2014 16:59:00 +0000</pubDate><atom:updated>2014-02-19T11:12:33.838-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">canvas</category><category domain="http://www.blogger.com/atom/ns#">flowable</category><category domain="http://www.blogger.com/atom/ns#">platypus</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Platypus - Canvas como Flowable, ejemplo resumen (13)</title><description>En la entrada anterior, vimos como trabajan los niveles de platypus, sin embargo no se vio el paso directo entre el nivel 1 (canvas) y el nivel 2 (flowables), ya que los dibujos creados en el nivel 1 fueron del tipo No-Flowables, usados como pie de página y encabezado.&lt;br /&gt;
&lt;br /&gt;
En este ejemplo veremos el uso de la clase Flowable, en la que heredaremos sus atributos y crear nosotros nuestros propios dibujos con canvas:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRj7MnInYTmHaAJlMTHz5YubZZel8adTIeFVNe0_74tPyEvBQWyheuVQgr7Avlm_TKB4-G43Xjbso5rjp4Dby2-EdHc29Q3HvciNjJhyFlngGnn_rVO4bDO2CGiOf9Bvh_9k7_-_tZDa4/s1600/Screenshot_6.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRj7MnInYTmHaAJlMTHz5YubZZel8adTIeFVNe0_74tPyEvBQWyheuVQgr7Avlm_TKB4-G43Xjbso5rjp4Dby2-EdHc29Q3HvciNjJhyFlngGnn_rVO4bDO2CGiOf9Bvh_9k7_-_tZDa4/s1600/Screenshot_6.png&quot; height=&quot;400&quot; width=&quot;312&quot; /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY_qwlESV2w2H14H47uAGLKgp9nNKcKyCzc8ytb9wYX4izDoft77ZmhZqKz2UqMT1runn9XC3q6ffyYzmAqtKH3BLPgJf6IQd-oABMLpSGjLNNrSEFqRGFvaGgZwP_-LyLK7XUj_YkCWs/s1600/Screenshot_7.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY_qwlESV2w2H14H47uAGLKgp9nNKcKyCzc8ytb9wYX4izDoft77ZmhZqKz2UqMT1runn9XC3q6ffyYzmAqtKH3BLPgJf6IQd-oABMLpSGjLNNrSEFqRGFvaGgZwP_-LyLK7XUj_YkCWs/s1600/Screenshot_7.png&quot; height=&quot;366&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;#-*- coding:utf-8 -*-
import os

#Librerias reportlab a usar:
from reportlab.platypus import (BaseDocTemplate, PageTemplate, 
NextPageTemplate, PageBreak, Frame, FrameBreak, Flowable, Paragraph, 
Image, Spacer)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import inch

#CREAMOS EL DOCTEMPLATE
#======================
doc = BaseDocTemplate(&#39;test.pdf&#39;, pagesize=A4) #landscape(A4) para Horizontal

#CREAMOS LOS CANVAS
#==================
def encabezado(canvas,doc):
    canvas.saveState()
    canvas.setFont(&#39;Times-Roman&#39;, 9)
    canvas.drawString(inch, A4[1] - 50, &quot;Ejemplo de DocTemplate y PageTemplate&quot;)
    canvas.line(inch, A4[1] - 60, A4[0] - 65, A4[1] - 60)
    canvas.restoreState()
    
def piePagina(canvas,doc):
    canvas.saveState()
    canvas.setFont(&#39;Times-Roman&#39;,9)
    canvas.drawString(inch, 0.75 * inch, &quot;Página %d&quot; % doc.page)
    canvas.restoreState()
    
#Creamos nuestro flowable. Se tiene que tener al menos un método wrap y draw    
class Rectangulo(Flowable):
    def __init__(self, ancho=206, alto=100):
        self.ancho = ancho
        self.alto = alto
    
    def wrap(self, *args):
        &quot;&quot;&quot;Provee el tamaño del área de dibujo&quot;&quot;&quot;
        return (self.ancho, self.alto)

    def draw(self):
        canvas = self.canv  # El atributo que permite dibujar en canvas
        canvas.saveState()
        canvas.setLineWidth(1)
        canvas.rect(0, 0, self.ancho, self.alto, fill=0)
        canvas.restoreState()

#Modifiquemos un flowable existente
class RotarImagen(Image):
    def wrap(self, availWidth, availHeight):
        self.w, self.h = Image.wrap(self, availWidth, availHeight)
        return self.w, self.h

    def draw(self):
        self.canv.translate(0,self.h)
        self.canv.rotate(-90)
        Image.draw(self)

#CREAMOS LOS FRAMES
#==================
#Frame (x1, y1, ancho, alto, leftPadding=6, bottomPadding=6, rightPadding=6,
#topPadding=6, id=None, showBoundary=0)

frame0 = Frame(doc.leftMargin, doc.bottomMargin, 
                doc.width, doc.height, showBoundary=1, id=&#39;normalBorde&#39;)
frame1 = Frame(doc.leftMargin, doc.bottomMargin, 
                doc.width, doc.height / 2, id=&#39;capitulo&#39;)
frame2 = Frame(doc.leftMargin, doc.bottomMargin, 
                doc.width /2 - 6, doc.height, id=&#39;col1&#39;)
frame3 = Frame(doc.leftMargin + doc.width / 2 + 6, doc.bottomMargin, 
                doc.width / 2 - 6, doc.height, id=&#39;col2&#39;)

#CREAMOS LOS PAGETEMPLATE
#========================
#PageTemplate(id=None,frames=[],onPage=_doNothing,onPageEnd=_doNothing)

doc.addPageTemplates([
    PageTemplate(id=&#39;caratula&#39;, frames=frame0),
    PageTemplate(id=&#39;capitulos&#39;, frames=frame1),
    PageTemplate(id=&#39;contenido&#39;, frames=[frame2, frame3], 
                 onPage = encabezado, onPageEnd=piePagina),
                    ])

#CREAMOS LOS FLOWABLES
#=====================
#Creamos la hoja de Estilo
estilo=getSampleStyleSheet()
estilo.add(ParagraphStyle(name = &quot;Titulo&quot;,  alignment=TA_CENTER, fontSize=20,
           fontName=&quot;Helvetica-BoldOblique&quot;))
           
#Iniciamos el platypus story
story=[]

#Creamos la carátula:
story.append(Spacer(0,200))
story.append(Image(&quot;Tux2.png&quot;, width=150, height=200))
story.append(Spacer(0,20))
titulo = Paragraph(&quot;&lt;u&gt;Ejemplo PageTemplate-DocTemplate&lt;/u&gt;&quot;, estilo[&#39;Titulo&#39;])
story.append(titulo)

#Creamos el contenido en general
story.append(NextPageTemplate(&#39;capitulos&#39;))
story.append(PageBreak())
story.append(Paragraph(&quot;Capítulo I: Conociendo ReportLab&quot;, estilo[&#39;Heading1&#39;]))
  
story.append(NextPageTemplate(&#39;contenido&#39;))
story.append(PageBreak())
story.append(Paragraph(&quot;Contenido del Capítulo I. &quot; * 300, estilo[&#39;Normal&#39;]))
                
story.append(NextPageTemplate(&#39;capitulos&#39;))
story.append(PageBreak())
story.append(Paragraph(&quot;Capítulo II: Sobre Platypus&quot;, estilo[&#39;Heading1&#39;]))

story.append(NextPageTemplate(&#39;contenido&#39;))
story.append(PageBreak())
story.append(Paragraph(&quot;Contenido de la columna I &quot;, estilo[&#39;Title&#39;]))
story.append(Paragraph(&quot;Lorem ipsum &quot;*140, estilo[&#39;BodyText&#39;]))
story.append(FrameBreak()) #Se mueve al siguiente frame del pagetemplate
story.append(Paragraph(&quot;Contenido de la columna II&quot;, estilo[&#39;Title&#39;]))
story.append(Paragraph(&quot;Domine Sanctus &quot;*50, estilo[&#39;BodyText&#39;]))
story.append(Paragraph(&quot;Veamos un rectángulo:&quot;, estilo[&#39;BodyText&#39;]))
story.append(Rectangulo())
story.append(Paragraph(&quot;Veamos un cuadrado:&quot;, estilo[&#39;BodyText&#39;]))
story.append(Rectangulo(50, 50))

I = RotarImagen(&quot;tuxito.png&quot;)
I.hAlign = &quot;CENTER&quot;
story.append(I)
                      
#CONSTRUIMOS EL PDF
#==================
doc.build(story)

os.system(&quot;test.pdf&quot;)

&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-canvas-como-flowable-ejemplo.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRj7MnInYTmHaAJlMTHz5YubZZel8adTIeFVNe0_74tPyEvBQWyheuVQgr7Avlm_TKB4-G43Xjbso5rjp4Dby2-EdHc29Q3HvciNjJhyFlngGnn_rVO4bDO2CGiOf9Bvh_9k7_-_tZDa4/s72-c/Screenshot_6.png" height="72" width="72"/><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-4639449990728887959</guid><pubDate>Sat, 15 Feb 2014 17:57:00 +0000</pubDate><atom:updated>2014-02-17T18:18:39.317-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">platypus</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Platypus - PageTemplate y DocTemplate (12)</title><description>Los niveles más altos en platypus son los PageTemplates y DocTemplates. Los DocTemplates están formados por un conjunto de PageTemplates.&lt;br /&gt;
&lt;br /&gt;
Los DocTemplates son expresado a trávez de &lt;b&gt;BaseDocTemplate&lt;/b&gt;, que es una clase que implementa la maquinaria básica para el formateo del documento. Posee un método &lt;b&gt;build&lt;/b&gt; que procesa una lista de Flowables (obviamente, estos almacenados en los frames, y los frames en los pagetemplates) y un método &lt;b&gt;addPageTemplates&lt;/b&gt; que agrega los pagetemplates. De esta forma se llega a producir el documento PDF a alto nivel.&lt;br /&gt;
&lt;br /&gt;
Los argumentos principales del BaseDocTemplate son los siguientes:&lt;br /&gt;
&lt;br /&gt;
BaseDocTemplate( nombreArchivo,&amp;nbsp; &lt;span style=&quot;color: #990000;&quot;&gt;# Nombre de nuestro pdf&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pagesize=defaultPageSize,&amp;nbsp;&lt;span style=&quot;color: #990000;&quot;&gt; # Tamaño de página&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pageTemplates=[],&amp;nbsp;&lt;span style=&quot;color: #990000;&quot;&gt; # Lista de pagetemplates&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; showBoundary=0,&amp;nbsp; &lt;span style=&quot;color: #990000;&quot;&gt;# Para mostrar el borde&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; leftMargin=inch,&amp;nbsp;&lt;span style=&quot;color: #990000;&quot;&gt; # Magen izquierdo&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rightMargin=inch,&amp;nbsp; &lt;span style=&quot;color: #990000;&quot;&gt;# Margen derecho&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; topMargin=inch,&amp;nbsp;&lt;span style=&quot;color: #990000;&quot;&gt; # Margen superior&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bottomMargin=inch,&amp;nbsp; &lt;span style=&quot;color: #990000;&quot;&gt;# Margen inferior&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; title=None,&amp;nbsp;&lt;span style=&quot;color: #990000;&quot;&gt; # Titulo del pdf&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; author=None,&amp;nbsp;&lt;span style=&quot;color: #990000;&quot;&gt; # Autor del pdf&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
El &lt;b&gt;SimpleDocTemplate &lt;/b&gt;(from reportlab.platypus import SimpleDocTemplate), es una platilla de documento predefinida, cuyo uso por lo general se da en relación con el canvas. No usa una lista de pagetemplates, pero nos asigna uno. Además, en su método build, se puede usar &lt;b&gt;onFirstPage &lt;/b&gt;y &lt;b&gt;onLaterPages&lt;/b&gt;, como modelos de primera página y páginas posteriores. (&lt;a href=&quot;http://menteleal.blogspot.com/2014/02/report-lab-platypus-entendiendo-la.html&quot;&gt;ejemplo&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
En cuanto a los &lt;b&gt;PageTemplates&lt;/b&gt;, que son contenedores de los Frames, poseen los siguientes argumentos: &lt;br /&gt;
&lt;br /&gt;
PageTemplate(id=None,&amp;nbsp; # Identificador&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; frames=[],&amp;nbsp; # Lista de frames&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; onPage=_doNothing,&amp;nbsp; # Por lo general es usado como encabezado&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; onPageEnd=_doNothing&amp;nbsp; # Por lo general es usado como pie de página&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; ) &lt;br /&gt;
&lt;br /&gt;
Tanto &lt;b&gt;onPage &lt;/b&gt;como &lt;b&gt;onPageEnd&lt;/b&gt; deben ser llamados por una función, que tiene la estructura siguiente:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
def XXX(canvas, documento)&lt;/div&gt;
&lt;br /&gt;
Esas dos rutinas, en si tienen el objetivo de dibujar, partes estáticas en las páginas, que no son fluibles como los flowables (&lt;b&gt;No-Flowables&lt;/b&gt;). Es por eso, que por lo general su uso se centra en encabezado, pies de página, marcas de agua.&lt;br /&gt;
&lt;br /&gt;
Ahora, veamos el ejemplo de cómo usar el pagetemplate y doctemplate&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisKamsATnsxyaY1JqADAfSK-rfLGCBMotJEyHYdvadyfNaJrUvC8UdWf01SeAVdI8fRNCR60cHD50MptqkUIruO0ibdJ1rEJJ2K0A9OAmZn_Eu1eaAxmYmzQX2illy_JtrAPrv0KFp6_8/s1600/Screenshot_5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisKamsATnsxyaY1JqADAfSK-rfLGCBMotJEyHYdvadyfNaJrUvC8UdWf01SeAVdI8fRNCR60cHD50MptqkUIruO0ibdJ1rEJJ2K0A9OAmZn_Eu1eaAxmYmzQX2illy_JtrAPrv0KFp6_8/s1600/Screenshot_5.png&quot; height=&quot;358&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;#-*- coding:utf-8 -*-
import os

#Librerias reportlab a usar:
from reportlab.platypus import (BaseDocTemplate, Frame, Paragraph, 
                    NextPageTemplate, PageBreak, PageTemplate)
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
from reportlab.lib.pagesizes import A4


#NIVEL 1: CREAMOS LOS CANVAS
#===========================   
#Creamos los canvas para el pie de página y encabezado, que serán fijos
def encabezado(canvas,doc):
    canvas.saveState()
    canvas.setFont(&#39;Times-Roman&#39;,9)
    canvas.drawString(inch, A4[1]-50, &quot;Ejemplo de DocTemplate y PageTemplate&quot;)
    canvas.restoreState()
    
def pie(canvas,doc):
    canvas.saveState()
    canvas.setFont(&#39;Times-Roman&#39;,9)
    canvas.drawString(inch, 0.75 * inch, &quot;Page %d&quot; % doc.page)
    canvas.restoreState()

#NIVEL 2: CREAMOS LOS FLOWABLES
#==============================
#Creamos la hoja de Estilo
estilo=getSampleStyleSheet()

#Iniciamos el platypus story
story=[]

#Añadimos al story los flowables. Hay que tener en cuenta que se inicia
#con el primer pageTemplate &quot;UnaColumna&quot;
story.append(Paragraph(&quot;Esto es el texto del Frame normal del pagetemplate&quot; +\
                       &quot; de una columna&quot;* 500, estilo[&#39;Normal&#39;]))
                        
story.append(NextPageTemplate(&#39;DosColumnas&#39;))  # Cambio de PageTemplate
story.append(PageBreak())  # Inicio en otra hoja
story.append(Paragraph(&quot;Esto es el texto del Frame que pertenece al&quot; +\
                       &quot; pagetemplate de dos columnas&quot; * 500, estilo[&#39;Normal&#39;]))
                
story.append(NextPageTemplate(&#39;UnaColumna&#39;))
story.append(PageBreak())
story.append(Paragraph(&quot;Regresamos al texto del Frame normal del&quot; +\
                        &quot; pagetemplate de dos columnas&quot;*100, estilo[&#39;Normal&#39;]))

#NIVEL 3: CREAMOS LOS FRAMES, para luego asignarlos a un pagetemplate.
#===========================
#Frame (x1, y1, ancho, alto, leftPadding=6, bottomPadding=6, rightPadding=6,
# topPadding=6, id=None, showBoundary=0)

#1. Frame que contendrá a toda el contenido de una hoja
frameN = Frame(inch, inch, 451, 697, id=&#39;normal&#39;)

#2. Frame de columnas
frame1 = Frame(inch, inch, 220, 697, id=&#39;col1&#39;)
frame2 = Frame(inch + 230, inch, 220, 697, id=&#39;col2&#39;)

#NIVEL 4: CREAMOS LOS PAGETEMPLATE, le asignamos los frames y los canvas
#=================================
#PageTemplate(id=None,frames=[],onPage=_doNothing,onPageEnd=_doNothing)
PTUnaColumna = PageTemplate(id=&#39;UnaColumna&#39;, frames=frameN, onPage=pie)
PTDosColumnas =  PageTemplate(id=&#39;DosColumnas&#39;, frames=[frame1,frame2],
                        onPage=encabezado, onPageEnd=pie)

#NIVEL 5: CREAMOS EL DOCTEMPLATE, a partir del BaseDocTemplate
#===============================
doc = BaseDocTemplate(&#39;test.pdf&#39;, pageTemplates=[PTUnaColumna, PTDosColumnas], 
        pagesize=A4)

#Construimos el PDF
doc.build(story)

os.system(&quot;test.pdf&quot;)
&lt;/pre&gt;
Si han sido observadores, no ha habido un paso directo entre el nivel 1 y el nivel 2, y eso se debe a que los canvas que usamos son NO FLOWABLES, que han sido usados directamente en los pagetemplates del nivel 4. En el siguiente post, veremos como usar canvas en flowables y otras cosas más.</description><link>http://menteleal.blogspot.com/2014/02/reportlab-pagetemplate-y-doctemplate-12.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisKamsATnsxyaY1JqADAfSK-rfLGCBMotJEyHYdvadyfNaJrUvC8UdWf01SeAVdI8fRNCR60cHD50MptqkUIruO0ibdJ1rEJJ2K0A9OAmZn_Eu1eaAxmYmzQX2illy_JtrAPrv0KFp6_8/s72-c/Screenshot_5.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-5528774255382703597</guid><pubDate>Thu, 13 Feb 2014 22:14:00 +0000</pubDate><atom:updated>2014-02-13T17:17:58.541-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">canvas</category><category domain="http://www.blogger.com/atom/ns#">platypus</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Platypus - Frames (11)</title><description>Los Frames son contenedores activos, quienes a su vez son contenidos en un PageTemplates. Tienen una localización y tamañon, manteniendo el concepto de espacio dibujable restante.&lt;br /&gt;
&lt;br /&gt;
Frame (x1, y1, ancho, alto, leftPadding=6, bottomPadding=6, rightPadding=6, topPadding=6, id=None, showBoundary=0)&lt;br /&gt;
&lt;br /&gt;
El comando anterior, crear una instancia del Frame con cordenadas x,y que son relativas a la página en uso. Los Padding reducen espacio para dibujar. El id, sirve como un identificador (ej: &#39;ColumnaDerecha&#39;). Si el showBoundary es distinto de cero, se mostrará las fronteras del frame en tiempo de ejecución.&lt;br /&gt;
&lt;br /&gt;
- &lt;b&gt;Frame.addFromList(drawList, canvas)&lt;/b&gt; Añade la lista de flowables&lt;br /&gt;
- &lt;b&gt;Frame.split(flowable, canvas)&lt;/b&gt; Devuelve una lista de flowables&lt;br /&gt;
- &lt;b&gt;Frame.drawBoundary(canvas)&lt;/b&gt; Dibuja el marco del Frame&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji3m59cncTqXkwIxDDsgQW9YhqSpZyYqrh3ogxuXpf7w7YjCAKKnQcLBfvIaxqLfSECwzdtmvMDy7kfRvuvj63Mk8j5cENGVSLCH5Ss1V4BECnc-xwESWHbn8vh7NfaZzKScucdbobHUI/s1600/Screenshot_4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji3m59cncTqXkwIxDDsgQW9YhqSpZyYqrh3ogxuXpf7w7YjCAKKnQcLBfvIaxqLfSECwzdtmvMDy7kfRvuvj63Mk8j5cENGVSLCH5Ss1V4BECnc-xwESWHbn8vh7NfaZzKScucdbobHUI/s1600/Screenshot_4.png&quot; height=&quot;400&quot; width=&quot;290&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Veamos el ejemplo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;import os

#Cargamos los módulos que necesitamos.

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
from reportlab.platypus import Paragraph, Frame
from reportlab.platypus import Image
from reportlab.platypus import Spacer

#Creamos objeto Canvas.
c = Canvas(&#39;test.pdf&#39;)

#Estilo de la hoja.
estiloHoja = getSampleStyleSheet()

#Demás estilos.
estiloN = estiloHoja[&#39;Normal&#39;]
estiloH = estiloHoja[&#39;BodyText&#39;]

#Inicializamos platypus story.
story = []

#Añadimos algunos flowables.
imagen_logo = Image(&quot;Tux2.png&quot;, width=150, height=200)
story.append(imagen_logo)

#Dejamos espacio.
story.append(Spacer(0,20))

#Añadimos un párrafo.
story.append(Paragraph(&quot;Esto es un ejemplo de frame 01&quot;,estiloN))

#Definimos un frame.
frame = Frame(3, 3, 200, 260, showBoundary=1)
frame.addFromList(story, c)

#Inicializamos platypus story.
story2 = []

#Añadimos algunos flowables.
story2.append(Paragraph(&quot;Este es el párrafo del segundo Frame&quot;,estiloH))

#Dejamos espacio.
story2.append(Spacer(0,20))

#~ #Una imagen.
imagen_logo = Image(&quot;imagen.jpg&quot;, width=100, height=100)
story2.append(imagen_logo)

#Definimos otro frame.
frame2 = Frame(250, 3, 250, 250, 6, showBoundary=1)
frame2.addFromList(story2, c)

#Salvamos el PDF.
c.save()

os.system(&quot;test.pdf&quot;)
&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-platypus-frames-11.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji3m59cncTqXkwIxDDsgQW9YhqSpZyYqrh3ogxuXpf7w7YjCAKKnQcLBfvIaxqLfSECwzdtmvMDy7kfRvuvj63Mk8j5cENGVSLCH5Ss1V4BECnc-xwESWHbn8vh7NfaZzKScucdbobHUI/s72-c/Screenshot_4.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-3357983371880291897</guid><pubDate>Thu, 13 Feb 2014 21:32:00 +0000</pubDate><atom:updated>2014-02-13T16:33:33.736-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">canvas</category><category domain="http://www.blogger.com/atom/ns#">platypus</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab. Platypus - Flowables (10)</title><description>Ya vimos en temas anteriores el nivel más bajo de todos, el pdfgen.canvas. Ahora veremos las capas superiores, que en su conjunto serán usadas por Platypus.&lt;br /&gt;
&lt;br /&gt;
El Flowables es una clase abstracta para cosas que pueden ser dibujadas; por ejemplo: los párrafos y las tablas. Usa métodos como:&lt;br /&gt;
&lt;br /&gt;-&lt;b&gt; Flowable.drawOn(canvas, x, y) &lt;/b&gt;Envía el flowable a un canvas en particular. Maneja el traslado de las coordenadas del canvas (x,y) , de manera que dicho canvas pueda dibujar el flowable en un frame de coordenadas absolutas.&lt;br /&gt;
&lt;br /&gt;- &lt;b&gt;Flowable.wrap(width, height)&lt;/b&gt; Calcula el espacio que usará el flowable.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoZ1cnud2hi6lAe_qY9I_STQK-9LQdAz_vRBMeWrtsFtDIkQ0vi12cni2fnKnL_oJYS6MB904Yf5uOgyBraVgS7st4z4eneyvEjQKcxCrJFQETnfLu3Zvrmmt8-5gqgnyXlZpy2NbyUnM/s1600/Screenshot_3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoZ1cnud2hi6lAe_qY9I_STQK-9LQdAz_vRBMeWrtsFtDIkQ0vi12cni2fnKnL_oJYS6MB904Yf5uOgyBraVgS7st4z4eneyvEjQKcxCrJFQETnfLu3Zvrmmt8-5gqgnyXlZpy2NbyUnM/s1600/Screenshot_3.png&quot; height=&quot;320&quot; width=&quot;305&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;
# -*- coding:utf-8 -*-
import os
from reportlab.platypus import Paragraph
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import A4

hojaEstilo = getSampleStyleSheet()
estilo = hojaEstilo[&#39;BodyText&#39;]

P=Paragraph(&#39;Un pequeño ejemplo&#39;, estilo)

c = Canvas(&#39;test.pdf&#39;)

#Supongamos que nuestro frame sea el tamaño de la hoja A4
PAGE_WIDTH = A4[0]
PAGE_HEIGHT = A4[1]

#El párrafo tiene un ancho y un alto respectivo, por lo tanto el método wrap
#calculará el espacio que realmente se requiere para reajustar el Flowable, 
#en este caso el párrafo.
w, h = P.wrap(PAGE_WIDTH, PAGE_HEIGHT)   
print w, h
#Hay que tener en cuenta que el ancho del párrafo se extiende por el ancho de
#la página.

#Especificamos en que altura del eje Y se ubicará el párrafo   
UbicacionParrafo= PAGE_HEIGHT - h
#Mandamos el Flowable(el párrafo), al canvas.
P.drawOn(c, 0, UbicacionParrafo)

c.save()

os.system(&quot;test.pdf&quot;)
&lt;/pre&gt;</description><link>http://menteleal.blogspot.com/2014/02/reportlab-platypus-flowables-10.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoZ1cnud2hi6lAe_qY9I_STQK-9LQdAz_vRBMeWrtsFtDIkQ0vi12cni2fnKnL_oJYS6MB904Yf5uOgyBraVgS7st4z4eneyvEjQKcxCrJFQETnfLu3Zvrmmt8-5gqgnyXlZpy2NbyUnM/s72-c/Screenshot_3.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-5096402613412868382</guid><pubDate>Thu, 13 Feb 2014 17:25:00 +0000</pubDate><atom:updated>2014-02-13T12:26:45.509-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">canvas</category><category domain="http://www.blogger.com/atom/ns#">platypus</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Platypus - Entendiendo la relación con pdfgen.canvas (09)</title><description>Platypus (Page Layout and Typography Using Scripts), es una librería para disponer las páginas en un alto nivel, permitiendonos crear documentos complejos con poco esfuerzo.&lt;br /&gt;
&lt;br /&gt;
Platypus busca separar el diseño del contenido de los documentos. Así por ejemplo, los párrafos son construidos usando estilo de párrafos, y las páginas usando plantillas. De esta forma, si se crea un millar de páginas, bastará con modificar las especificaciones de estilo para que resulte efecto en todo el documento.&lt;br /&gt;
&lt;br /&gt;
Platypus usa un diseño de capas:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;DocTemplates&lt;/b&gt;: Es la plantilla del documento.&lt;br /&gt;
&lt;b&gt;PageTemplates&lt;/b&gt;: Es la plantilla para las páginas.&lt;br /&gt;
&lt;b&gt;Frames&lt;/b&gt;: Son las regiones en las páginas que contienen texto o gráficos&lt;br /&gt;
&lt;b&gt;Flowables&lt;/b&gt;: Elementos de texto ó gráficos que 
están incrustados en el documento (párrafos, tablas, imágenes, pero no 
pies de página)&lt;br /&gt;
&lt;b&gt;pdfgen.Canvas&lt;/b&gt;: El que se encarga de pintar el documento, a partir de las órdenes de las otras capas superiores.&lt;br /&gt;
&lt;br /&gt;
El gráfico siguiente lo explica mejor ( Los de color púrpura son los Frames): &lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizg40h088LRl-0UgcEcd53MTQNc4n0gv6pTm7A7ztyDEvG1X6cZ4_7o7_4O-_S_j1ez4TWwO-0EBR61soX9yZy2Krt60sSYE_V-guZkQ9mL9dOeo9YU-3mj5MKlCwdJ1JO8fND4yYrRQU/s1600/Screenshot_1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizg40h088LRl-0UgcEcd53MTQNc4n0gv6pTm7A7ztyDEvG1X6cZ4_7o7_4O-_S_j1ez4TWwO-0EBR61soX9yZy2Krt60sSYE_V-guZkQ9mL9dOeo9YU-3mj5MKlCwdJ1JO8fND4yYrRQU/s1600/Screenshot_1.png&quot; height=&quot;226&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Veamos un ejemplo:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxV5syE69vw4p7xPH4UjD3uhyatqfUxDJRZmcTik2m1Z-KKymPKJ5-1GrZbQjH3IUvZcPpC3Ws1C3ZgEfmknvw0Q9Ow8xGIyiMFqh2kKPTqbf-5zSkLYkVj_HkV8GrMf-qX5QDairf1ZI/s1600/Screenshot_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxV5syE69vw4p7xPH4UjD3uhyatqfUxDJRZmcTik2m1Z-KKymPKJ5-1GrZbQjH3IUvZcPpC3Ws1C3ZgEfmknvw0Q9Ow8xGIyiMFqh2kKPTqbf-5zSkLYkVj_HkV8GrMf-qX5QDairf1ZI/s1600/Screenshot_2.png&quot; height=&quot;320&quot; width=&quot;249&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;pre class=&quot;brush:py&quot;&gt;
# -*- coding:utf-8 -*-
import os

#Importamos algunas librerias: SimpleDocTemplate, es una plantilla de documento
#predefinida; getSampleStyleSheet, contiene una hoja de estilos de ejemplo;
#inch es una pulgada
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch

PAGE_WIDTH = A4[0]
PAGE_HEIGHT = A4[1]

styles = getSampleStyleSheet()

#Definimos las caracteristicas fijas de la primera página
def myFirstPage(canvas, doc):
    canvas.saveState()
    canvas.setFont(&#39;Times-Bold&#39;, 16)
    canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT - 108, Title)
    canvas.setFont(&#39;Times-Roman&#39;, 9)
    canvas.drawString(inch, 0.75 * inch, &quot;Primera pagina / %s&quot; %pageinfo)
    canvas.restoreState()

#Definimos disposiciones alternas para las caracteristicas de las otras páginas
def myLaterPages(canvas, doc):
    canvas.saveState()
    canvas.setFont(&#39;Times-Roman&#39;, 9)
    canvas.drawString(inch, 0.75 * inch, &quot;Página %d / %s&quot; %(doc.page, pageinfo))
    canvas.restoreState()


Title = &quot;Hola mundo&quot;
pageinfo = &quot;Ejemplo Platypus&quot;
#Creamos un documento basándonos en una plantilla
doc = SimpleDocTemplate(&quot;test.pdf&quot;)
#Iniciamos el story para los registros
story = [Spacer(0, 80)]
#Definimos un estilo
estilo = styles[&#39;Normal&#39;]
#Creamos 100 párrafos
for i in range (100):
    texto = (&quot;Este es el párrafo número %s. &quot; %(i+1) ) *20
    #Definimos un párrafo usando un estilo
    p = Paragraph(texto, estilo)
    #Registramos en el story
    story.append(p)
    #También registramos el espacio que tendrá entre párrafos
    story.append(Spacer(0, 20))
#Construimos el documento a partir de los argumentos definidos
doc.build(story, onFirstPage = myFirstPage, onLaterPages = myLaterPages)

os.system(&quot;test.pdf&quot;)
&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/report-lab-platypus-entendiendo-la.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizg40h088LRl-0UgcEcd53MTQNc4n0gv6pTm7A7ztyDEvG1X6cZ4_7o7_4O-_S_j1ez4TWwO-0EBR61soX9yZy2Krt60sSYE_V-guZkQ9mL9dOeo9YU-3mj5MKlCwdJ1JO8fND4yYrRQU/s72-c/Screenshot_1.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-6669353770149955490</guid><pubDate>Thu, 06 Feb 2014 16:23:00 +0000</pubDate><atom:updated>2014-02-06T11:56:04.177-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">python</category><title>Python: Convertir variable a cadena</title><description>Una de las cosas particulares que encontré en la red, fue el de convertir una variable en una cadena.&lt;br /&gt;
Claro, algunos no le verán el sentido, ya que se podría usar diccionarios, pero sé que en algún momento podría ser útil.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX53aVPTh2nyOxTjAjFZ4v3Lzl19T_ewfOUBQVup02mb5UsN9B1nfUxgs2eUbfpy0sFwMlgAUPauD09tubcw4EEZXwUqFXFwMQ7Ajocvpi_8z4UDwFCyLXej54EmOjIQeXaz913Pq9wdo/s1600/Screenshot_18.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX53aVPTh2nyOxTjAjFZ4v3Lzl19T_ewfOUBQVup02mb5UsN9B1nfUxgs2eUbfpy0sFwMlgAUPauD09tubcw4EEZXwUqFXFwMQ7Ajocvpi_8z4UDwFCyLXej54EmOjIQeXaz913Pq9wdo/s1600/Screenshot_18.png&quot; height=&quot;187&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;a = &quot;algo&quot;
b = 512
c = None

def vartostr(var):
    return [name for name, ref in globals().iteritems() if ref is var][0]

lista = [a, b, c]
for i in lista:
    print &quot;Estos son los valores de la variable %s: %s&quot; %(vartostr(i), i)
&lt;/pre&gt;

</description><link>http://menteleal.blogspot.com/2014/02/python-convertir-variable-cadena.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX53aVPTh2nyOxTjAjFZ4v3Lzl19T_ewfOUBQVup02mb5UsN9B1nfUxgs2eUbfpy0sFwMlgAUPauD09tubcw4EEZXwUqFXFwMQ7Ajocvpi_8z4UDwFCyLXej54EmOjIQeXaz913Pq9wdo/s72-c/Screenshot_18.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-6143531750420286765</guid><pubDate>Tue, 04 Feb 2014 17:17:00 +0000</pubDate><atom:updated>2014-02-04T12:17:18.253-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">python</category><title>Mostrar Folder con python en multiplataforma</title><description>Al crear una aplicación quería lanzar un Folder, para que el usuario lo viera. Me encontré con varias soluciones, pero no las he probado todas en multiplataforma.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhitZHAGvZ7gpNrkYnUNaeOdiS4nVhUOhAXu51MN5vjjapSR5mz5FyQYRHNEBHUalDNKCkgnAMpb19P-Kk3m-_4hX2ZtGWVCLPzOFyYJbNsSVpUGuH-6Yja89lXTpwCwMkIBxl0FRDqjl4/s1600/open-folder-document-clip-art-12174.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhitZHAGvZ7gpNrkYnUNaeOdiS4nVhUOhAXu51MN5vjjapSR5mz5FyQYRHNEBHUalDNKCkgnAMpb19P-Kk3m-_4hX2ZtGWVCLPzOFyYJbNsSVpUGuH-6Yja89lXTpwCwMkIBxl0FRDqjl4/s1600/open-folder-document-clip-art-12174.jpg&quot; height=&quot;180&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Supongo que la desición radica en cúan multiplataforma es la solución, como en el caso de Linux, si la solución se aplica a la mayoría de distros.&lt;br /&gt;
&lt;br /&gt;
Solución 01&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;import os
import platform

def open_file(path):
    if platform.system() == &quot;Windows&quot;:
        os.startfile(path)
    elif platform.system() == &quot;Darwin&quot;:
        subprocess.Popen([&quot;open&quot;, path])
    else:
        subprocess.Popen([&quot;xdg-open&quot;, path])

open_file(path)
&lt;/pre&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Solución 02&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;import webbrowser
webbrowser.open(path)
&lt;/pre&gt;
Solución 03 &lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;import os
systems = {
    &#39;nt&#39;: os.startfile,
    &#39;posix&#39;: lambda foldername: os.system(&#39;xdg-open &quot;%s&quot;&#39; % foldername),
    &#39;os2&#39;: lambda foldername: os.system(&#39;open &quot;%s&quot;&#39; % foldername)
     }

systems.get(os.name, os.startfile)(path)
&lt;/pre&gt;
Obviamente hay más soluciones, si tienen alguna compartanla. 
&lt;br /&gt;
&lt;br /&gt;</description><link>http://menteleal.blogspot.com/2014/02/mostrar-folder-con-python-en.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhitZHAGvZ7gpNrkYnUNaeOdiS4nVhUOhAXu51MN5vjjapSR5mz5FyQYRHNEBHUalDNKCkgnAMpb19P-Kk3m-_4hX2ZtGWVCLPzOFyYJbNsSVpUGuH-6Yja89lXTpwCwMkIBxl0FRDqjl4/s72-c/open-folder-document-clip-art-12174.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-1741723284387914132</guid><pubDate>Mon, 03 Feb 2014 21:16:00 +0000</pubDate><atom:updated>2014-02-03T16:16:42.935-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Insertando Fuentes TTF (08)</title><description>Insertar fuentes TrueType, se puede realizar no solo con pdfgen.canvas, sino también con platypus (que lo veremos más adelante). &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRE_RdWkm_jRlD3Cwi-UrgdmxqcfOUHorV7HZ-sGFPx0n_0QkBQjzH-zWjHX5JFNQbs8aV7kDrV1xHzT39o0zdBRk-L2eV9yhM6oFUM8VgfiBZAkIWvVmCI4Hk6OcC0QehHraMAzyDHsM/s1600/Screenshot_14.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRE_RdWkm_jRlD3Cwi-UrgdmxqcfOUHorV7HZ-sGFPx0n_0QkBQjzH-zWjHX5JFNQbs8aV7kDrV1xHzT39o0zdBRk-L2eV9yhM6oFUM8VgfiBZAkIWvVmCI4Hk6OcC0QehHraMAzyDHsM/s1600/Screenshot_14.png&quot; height=&quot;260&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
Para el ejemplo, hemos descargado una fuente cualquiera, muchas en la web, llamada &quot;COMICATE.ttf&quot;, en este caso veremos la inserción en canvas.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:py&quot;&gt;# -*- coding:utf-8 -*-
import os
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

#TTFont(nombre, archivo)
pdfmetrics.registerFont(TTFont(&#39;COMICATE&#39;, &#39;COMICATE.ttf&#39;))

c=canvas.Canvas(&quot;test.pdf&quot;, pagesize = A4)
c.drawString(100, 700, &quot;Texto sin usar fuente ttf&quot;)

c.setFont(&#39;COMICATE&#39;, 20)
c.drawString(100, 600, &quot;Texto usando fuente ttf&quot;)

c.showPage()

c.save()
os.system(&quot;test.pdf&quot;)

&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-insertando-fuentes-ttf-08.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRE_RdWkm_jRlD3Cwi-UrgdmxqcfOUHorV7HZ-sGFPx0n_0QkBQjzH-zWjHX5JFNQbs8aV7kDrV1xHzT39o0zdBRk-L2eV9yhM6oFUM8VgfiBZAkIWvVmCI4Hk6OcC0QehHraMAzyDHsM/s72-c/Screenshot_14.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-1227830633801323933</guid><pubDate>Mon, 03 Feb 2014 20:54:00 +0000</pubDate><atom:updated>2014-02-03T15:54:18.723-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Encoding UTF8 - Solución UnicodeDecodeError: &#39;utf8&#39; (07)</title><description>El error siguiente:&lt;span style=&quot;color: red;&quot;&gt; UnicodeDecodeError: &#39;utf8&#39; codec can&#39;t decode bytes in position...&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;span style=&quot;color: red;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx4VnqUnWCW3SmipVckFNVJ8Ahx814_xaLwO8qrIzVaMD18z5Rg3fTRieOSorI9kFcqI5x_dy6z4HvEx0Ym86pePtYCDheVsmCEFFAOVgJrVPqgRZ5HESus5YrCAa5ORfrhTzU1JkAInQ/s1600/Screenshot_13.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx4VnqUnWCW3SmipVckFNVJ8Ahx814_xaLwO8qrIzVaMD18z5Rg3fTRieOSorI9kFcqI5x_dy6z4HvEx0Ym86pePtYCDheVsmCEFFAOVgJrVPqgRZ5HESus5YrCAa5ORfrhTzU1JkAInQ/s1600/Screenshot_13.png&quot; height=&quot;80&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style=&quot;color: red;&quot;&gt;&lt;span style=&quot;color: black;&quot;&gt;por lo general aparece cuando leemos datos de otra fuente el cuál contiene datos en bytes, como latin-1, ANSI, estos se necesitan convertir a Unicode. Python provee tal conversión, por lo tanto la solución es inmediata.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: red;&quot;&gt;&lt;span style=&quot;color: black;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;span style=&quot;color: red;&quot;&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: red;&quot;&gt;&lt;span style=&quot;color: black;&quot;&gt;En el ejemplo tenemos un texto guardado en ANSI, cuyo contenido es &quot;Aquí un texto sin canción&quot;, en el que se produce un error al momento de dibujarlo en el canvas. Sin embargo, usando unicode(), todo se resuelve. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;# -*- coding:utf-8 -*-
import os
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

c=canvas.Canvas(&quot;test.pdf&quot;, pagesize = A4)

archivo = open(&quot;texto en latin.txt&quot;, &quot;r&quot;)
for linea in archivo:
    linea = unicode(linea, &#39;latin-1&#39;) #Solucionamos el problema de codificación
    c.drawString(100, 700, linea.strip())  # strip quita caracteres en blanco

c.showPage()

c.save()
os.system(&quot;test.pdf&quot;)
&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-encoding-utf8-solucion.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx4VnqUnWCW3SmipVckFNVJ8Ahx814_xaLwO8qrIzVaMD18z5Rg3fTRieOSorI9kFcqI5x_dy6z4HvEx0Ym86pePtYCDheVsmCEFFAOVgJrVPqgRZ5HESus5YrCAa5ORfrhTzU1JkAInQ/s72-c/Screenshot_13.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-1302180862398314359</guid><pubDate>Mon, 03 Feb 2014 17:46:00 +0000</pubDate><atom:updated>2014-02-03T12:47:18.531-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: pdfgen - Objeto de trayectoria y Tipo de líneas (06)</title><description>Ya vimos sobre los objetos de texto, que permiten dibujar de forma más comoda los textos. Para los gráficos, contamos con path object. La ventaja de usarlo, reside en la comparativa de dibujar a mano alzada, en la que el cierre de los puntos de unión se da automáticamente.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBWj7gFcfa-HvsVI8e-0U0TEX8kK-iCTA-RQ55QviqzmntRhM4peLwTL-KKVZEpCTPLU27ECdPcxa0ofd7g5H3XHsZNJU9eqN7DADL16hhNLCzNn9OBV3OGsvdMF9kemUJpBp4R1fNr2U/s1600/Screenshot_12.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBWj7gFcfa-HvsVI8e-0U0TEX8kK-iCTA-RQ55QviqzmntRhM4peLwTL-KKVZEpCTPLU27ECdPcxa0ofd7g5H3XHsZNJU9eqN7DADL16hhNLCzNn9OBV3OGsvdMF9kemUJpBp4R1fNr2U/s1600/Screenshot_12.png&quot; height=&quot;253&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;En el ejemplo también veremos sobre los tipos de líneas, y con esto finalizaremos el aspecto gráfico con pdfgen.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;
# -*- coding:utf-8 -*-
import os
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from math import sqrt

c=canvas.Canvas(&quot;test.pdf&quot;, pagesize = A4)

#PATH OBJECT
#=================
#Creamos una estrella de 6 puntas. Como se sabe esta formada por la 
#intersección de dos triángulos equiláteros.

#1. Dibujemos de la forma clásica, línea a línea
def estrellaDavid(x1, y1, lado):
    l = lado  
    h = (l * sqrt(3) / 2)     
        
    c.line(x1, y1, x1 + l, y1)
    c.line(x1, y1, x1 + l / 2 , y1 + h)
    c.line(x1 + l, y1, x1 + l / 2, y1 + h)

    c.line(x1, y1 + 2*h/3, x1 + l, y1 + 2*h/3)
    c.line(x1, y1 + 2*h/3, x1 + l / 2, y1 + 2*h/3 - h)
    c.line(x1 + l, y1 + 2*h/3, x1 + l / 2, y1 + 2*h/3 - h)

c.drawString(100, 800, &quot;Dibujo línea a línea&quot;)
c.setLineWidth(5)
estrellaDavid(200, 600, 200)


#2. Dibujemos usando Objeto de trayectoria (path object).
#A diferencia del método anterior, es como dibujar teniendo un lapiz en mano. 
#Si tenemos que levantarlo usamos moveTo; si tenemos que trazarlo, lineTo, y 
#lo importante los puntos de unión se cierran con p.close()
def estrellaDavid_po(x1, y1, lado):
    l = lado  
    h = (l * sqrt(3) / 2)  
    p = c.beginPath()
    p.moveTo(x1, y1)  # Nos movemos a un punto
    p.lineTo(x1 + l, y1)  # Trazamos la linea hasta el punto indicado
    p.lineTo(x1 + l / 2, y1 + h)
    p.lineTo(x1 , y1)
    p.close()  # Cierra el trazo de la figura dibujada
    
    p.moveTo(x1, y1 + 2*h/3)
    p.lineTo(x1 + l, y1 + 2*h/3)
    p.lineTo(x1 + l / 2, y1 + 2*h/3 - h)
    p.lineTo(x1, y1 + 2*h/3)
    p.close()
    c.drawPath(p)
#Hay más métodos de los path objects mencionados en el userguide, como:
# p.curveTo(x1,y1,x2,y2,x3,y3)  Dibuja una curva Bezier
# p.arc(x1,y1,x2,y2,startAng=0, extent=90)  Dibuja elipses parciales
# p.arcTo(x1,y1,x2,y2,startAng=0, extent=90)
# p.rect(x, y, ancho, alto)
# p.ellipse(x, y, ancho, alto)
# p.circle (x_centrado, y_centrado, radio)

c.drawString(100, 400, &quot;Dibujo con path object. Notesé la unión de puntos.&quot;)
estrellaDavid_po(200, 200, 200)

c.showPage()

#TIPOS DE UNIÓN DE LINEAS (JOIN)
#========================
c.setLineWidth(5)  # Tamaño de línea
estrellaDavid_po(20, 600, 150)
c.setLineJoin(1)  # Línea redondeada. (0) Default: Es puntiaguda
estrellaDavid_po(220, 600, 150)
c.setLineJoin(2)  # Línea cuadrada
estrellaDavid_po(420, 600, 150)

#TIPOS DE EXTREMO DE LINEA (CAP)
#=========================
c.line(220, 400, 350, 400)
c.setLineCap(1)  # Extremo redondeado. (0) Default: Cuadrado Sin Proyección
c.line(220, 380, 350, 380)
c.setLineCap(2)  # Extremo Cuadrado Con Proyección
c.line(220, 360, 350, 360)

c.setLineWidth(0.5)
c.line(220, 420, 220, 340)
c.line(350, 420, 350, 340)

#LINEA ENTRECORTADAS (DASH)
#===================
c.setLineWidth(1)
c.setDash(6, 3)  # sucesión de 6 puntos trazados, y 3 no trazados
estrellaDavid_po(20, 150, 150)
c.setDash(1, 2)  # sucesión de 1 punto trazado y 2 no trazados
estrellaDavid_po(220, 150, 150)
c.setDash([1,3,5,3], 0)  # sucesión alternada en la lista. 0: punto de inicio
estrellaDavid_po(420, 150, 150)

c.showPage()

c.save()
os.system(&quot;test.pdf&quot;)
&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-pdfgen-objeto-de-trayectoria.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBWj7gFcfa-HvsVI8e-0U0TEX8kK-iCTA-RQ55QviqzmntRhM4peLwTL-KKVZEpCTPLU27ECdPcxa0ofd7g5H3XHsZNJU9eqN7DADL16hhNLCzNn9OBV3OGsvdMF9kemUJpBp4R1fNr2U/s72-c/Screenshot_12.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-3304566142521025896</guid><pubDate>Mon, 03 Feb 2014 17:28:00 +0000</pubDate><atom:updated>2014-02-03T12:28:09.388-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: pdfgen - La librería lib.colors y transparencia (05)</title><description>Por lo general, al rellenar dibujos usamos colores rgb, cmyk, escala de grises, insertando valores para que en combinación nos de un determinado color. Si uno quiere insertar de forma grosa; por ejemplo el color azul, lo puede hacer directamente desde lib.colors. Además que da la opción de insertar colores transparentes:

&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyxkjz01qfBYFkxVQI4Y5nCkwtpeDkp5Tkq9C6dNfdF7xtyXpHTE2sdEoA272T0uvBfgC-Z6xpbPebhsj26QxjZKZUBa_KZFTXQFsBI9WrZBI3CGrl2GXTRBzF8wOkGG6nYxinQVZR46s/s1600/Screenshot_10.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyxkjz01qfBYFkxVQI4Y5nCkwtpeDkp5Tkq9C6dNfdF7xtyXpHTE2sdEoA272T0uvBfgC-Z6xpbPebhsj26QxjZKZUBa_KZFTXQFsBI9WrZBI3CGrl2GXTRBzF8wOkGG6nYxinQVZR46s/s320/Screenshot_10.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Veamos el ejemplo:
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;# -*- coding:utf-8 -*-
import os
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.lib.colors import Color, green, red  # Traemos algunos colores

c=canvas.Canvas(&quot;test.pdf&quot;, pagesize = A4)

print c.getPageNumber()  # Número de página

c.setLineWidth(20)  # Tamaño de la linea
c.setStrokeColorRGB(0.5, 0.5, 0.5)
c.setFillColorRGB(0.9, 0.0, 0.0)
c.rect(200, 300, 200, 200, fill=1)

#Creando color transparente
rojoTransparente = Color(100, 0, 0, alpha=0.5 )

c.setFillColor(green)  # Utilizamos un color que ya tenemos
c.rect(255, 125, 100, 100, fill=1, stroke=False)
c.setFillColor(rojoTransparente)
c.rect(300, 175, 100, 100, fill=1, stroke=False)

c.showPage()

c.save()
os.system(&quot;test.pdf&quot;)
&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-pdfgen-la-libreria-libcolors.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyxkjz01qfBYFkxVQI4Y5nCkwtpeDkp5Tkq9C6dNfdF7xtyXpHTE2sdEoA272T0uvBfgC-Z6xpbPebhsj26QxjZKZUBa_KZFTXQFsBI9WrZBI3CGrl2GXTRBzF8wOkGG6nYxinQVZR46s/s72-c/Screenshot_10.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-6837588318605731407</guid><pubDate>Sat, 01 Feb 2014 16:54:00 +0000</pubDate><atom:updated>2014-02-01T11:58:15.052-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: pdfgen - Objeto de texto (04)</title><description>Al usar canvas.drawstring, nos vemos limitados a dibujar de forma lineal el texto, y si el texto es demasiado largo, no se mostrará en todo la página. Además, hay oportunidades en que nuestro texto lo tenemos en un archivo, talvez un txt. En esos casos se puede usar objectText.

&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAHImnPplhkxnRxdbb69yC6mjiKOAziPmiS28RrvIH816dKjIsR4iz9KLx7MvaVeUl7DBUTqiUZ3UhAyfwvgXfLAZWtEg2INfX_YYapFWdM0rgeeMvKSELwSX8l2XxqENmXlhvhxkTSpM/s1600/Screenshot_9.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAHImnPplhkxnRxdbb69yC6mjiKOAziPmiS28RrvIH816dKjIsR4iz9KLx7MvaVeUl7DBUTqiUZ3UhAyfwvgXfLAZWtEg2INfX_YYapFWdM0rgeeMvKSELwSX8l2XxqENmXlhvhxkTSpM/s320/Screenshot_9.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Veamos el siguiente código que lo explica (se usa un archivo llamado lorem.txt, que contiene un párrafo de &lt;a href=&quot;http://es.lipsum.com/&quot;&gt;Lorem Ipsum&lt;/a&gt;: &lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;
# -*- coding:utf-8 -*-
import os
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

c=canvas.Canvas(&quot;test.pdf&quot;, pagesize = A4)

#FUENTES EN CANVAS
#-----------------
texto = &quot;Lorem ipsum dolor sit amet&quot;
x, y = 150, 710
for fuente in c.getAvailableFonts():  # Lista disponible de fuentes
    c.setFont(fuente, 10)  # Cambiamos la fuente y el tamaño
    c.drawString(x, y, texto)
    c.setFont(&quot;Helvetica&quot;, 12) 
    c.drawRightString(x-10, y, fuente + &quot;:&quot;)
    y -= 20
 
#TRABAJANDO CON OBJETO DE TEXTO
#-------------------------------
# Indispensable para textos de varias lineas, ya que el método drawString 
# no podrá dibujar múltiples líneas:
textoArchivo = open(&quot;lorem.txt&quot;, &quot;r&quot;)  # Abrimos un archivo de texto
texto = &quot;&quot;&quot;Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 
sed diam nonumyeirmod tempor invidunt ut labore et dolore magna 
aliquyam erat, sed diamvoluptua. At vero eos et accusam et justo duo dolores 
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem 
ipsum dolor sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 
sed diam nonumyeirmod tempor invidunt ut labore et dolore magna aliquyam erat, 
sed diamvoluptua. At vero eos et accusam et justo duo dolores et ea reb&quot;&quot;&quot; 
 
textobject = c.beginText()  # Iniciamos el textobject
textobject.setTextOrigin(20, 400)  # Ubicamos el cursor donde dibujar
textobject.setFont(&quot;Helvetica-Oblique&quot;, 13)
for i in textoArchivo:
    i = i.replace(&quot;\n&quot;,&quot;&quot;)  # Remplazamos el salto de linea
    textobject.setCharSpace(0.5)  # Espacio entre caracteres 
    textobject.setWordSpace(1)  # Espacio entre palabras
    textobject.textLine(i)  # Dibujamos la linea
    textobject.moveCursor(5, 10)  # Movemos el cursor para luego escribir
textobject.setFillGray(0.4)  # Rellenamos con Escala de grises
textobject.setLeading(20)  # Espaciado entre lineas
textobject.textLines(texto)  # Insertamos el texto y con color gris
c.drawText(textobject)  # Dibujamos el texto pasando un objeto de texto
 
c.showPage()  

c.save()
os.system(&quot;test.pdf&quot;)

&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/02/reportlab-pdfgen-objeto-de-texto-04.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAHImnPplhkxnRxdbb69yC6mjiKOAziPmiS28RrvIH816dKjIsR4iz9KLx7MvaVeUl7DBUTqiUZ3UhAyfwvgXfLAZWtEg2INfX_YYapFWdM0rgeeMvKSELwSX8l2XxqENmXlhvhxkTSpM/s72-c/Screenshot_9.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-8645635015129949264</guid><pubDate>Sat, 01 Feb 2014 00:22:00 +0000</pubDate><atom:updated>2014-01-31T19:25:29.425-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: pdfgen - Insertando imágenes en canvas (03)</title><description>En ReportLab hay dos formas principales de insertar imágenes: una es usando reportlab.graphics.shapes y la otra es canvas. La diferencia reside en que canvas inserta la imágen en una posición estática, mientras que la otra permite operaciones de rotado, escalado y traslado.&lt;br /&gt;
&lt;br /&gt;
Si nuestro caso es solo insertar una imágen en cierta posición, sin modificarla y usando canvas, está es nuestra opción.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDxTftpDEbkLDxtk_LqrVv9U6MrSFPLz2pKRmuxqFVWuWe2xA-lcRTbd4T8Yjh67OPiWMhIH-PhCXAmOXVXHtGYnMfSI_syhfA8RhuLx4QwTeqQCYVy0nw5p5AnUhIXdRoz1ijyPpypzw/s1600/Screenshot_8.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDxTftpDEbkLDxtk_LqrVv9U6MrSFPLz2pKRmuxqFVWuWe2xA-lcRTbd4T8Yjh67OPiWMhIH-PhCXAmOXVXHtGYnMfSI_syhfA8RhuLx4QwTeqQCYVy0nw5p5AnUhIXdRoz1ijyPpypzw/s1600/Screenshot_8.png&quot; height=&quot;320&quot; width=&quot;236&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;# -*- coding:utf-8 -*-
import os
from reportlab.pdfgen import canvas
c=canvas.Canvas(&quot;test.pdf&quot;, pagesize = A4)
#drawImage(archivo, x, y, width=None, height=None)
c.drawImage(&quot;Tux2.png&quot;, 0, A4[1]/2, width=400, height=400)
c.showPage()
c.save()
os.system(&quot;test.pdf&quot;)
&lt;/pre&gt;
No hay que olvidar que para otros formatos de imágenes debemos tener instalado el &lt;a href=&quot;http://www.pythonware.com/products/pil/&quot;&gt;PIL&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;
Prueben con la misma imágen u otra, en la web la encontre con el nombre Tux2.png
</description><link>http://menteleal.blogspot.com/2014/01/reportlab-pdfgen-insertando-imagenes-en.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDxTftpDEbkLDxtk_LqrVv9U6MrSFPLz2pKRmuxqFVWuWe2xA-lcRTbd4T8Yjh67OPiWMhIH-PhCXAmOXVXHtGYnMfSI_syhfA8RhuLx4QwTeqQCYVy0nw5p5AnUhIXdRoz1ijyPpypzw/s72-c/Screenshot_8.png" height="72" width="72"/><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-3067051979781036825</guid><pubDate>Fri, 31 Jan 2014 23:41:00 +0000</pubDate><atom:updated>2014-01-31T18:41:18.154-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: pdfgen - Formas básicas y Texto en canvas (02)</title><description>Es esta parte veremos algunas operaciones de texto y creación de formas básicas.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoa0NHff3ob4SPWDZ1qvoXPhUNc6kMcceAlOoFF9aRcHs5IZ7SnpR7UvGUTOC85gmF4xusO2i_qTvw9jURZ5rLouYfhTkRBfNBuRNB_g21rcmhCEcJnJmZHFmMl6jcSaA52H7NabAiCBE/s1600/Screenshot_7.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoa0NHff3ob4SPWDZ1qvoXPhUNc6kMcceAlOoFF9aRcHs5IZ7SnpR7UvGUTOC85gmF4xusO2i_qTvw9jURZ5rLouYfhTkRBfNBuRNB_g21rcmhCEcJnJmZHFmMl6jcSaA52H7NabAiCBE/s1600/Screenshot_7.png&quot; height=&quot;276&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNmi4_Sd61388rYO3I9fuTDF6gbU59ColZ2SuWAXMCyZr-OJupnLpcC3AZu84-3aSw3MhlpIBA8Q2_Ozw-uU-F4tcpM2twVfFdx0hdJMmIp2wkKEzpAPd-Z2jlVsg8ws5GhqgEq6TEOPg/s1600/Screenshot_6.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;# -*- coding:utf-8 -*
import os
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch  # Tambien podemos usar otras medidas

c=canvas.Canvas(&quot;test.pdf&quot;, pagesize = A4)

#Ancho y alto de la página
ancho, alto = A4

#Definimos el tipo y tamaño de fuente
c.setFont(&quot;Helvetica&quot;, 24)

#Dibujamos un par de lineas, por omision serán de color negro
#-line(x1,y1,x2,y2) x1,y1 inicio de line; x2, y2 fin de linea
c.line(50,50,50,350)
c.line(50,50,350,50)

#Escogemos algunos colores
c.setStrokeColorRGB(0.0, 1, 0.0)  # Color de trazo
c.setFillColorRGB(0, 0.0, 0.5)  # Color de relleno

#Dibujamos un Cuadrado a partir de un rectángulo redondeado
#-roundRect(x, y, ancho, alto, radio de curva, stroke, fill)
#stroke y fill, si es 0 inidica no mostrar trazo ni relleno
c.roundRect(75, 75, 275, 257, 20, stroke = 1, fill = 1)
c.setFillColorRGB(0.75, 0.75, 0.0)  # Relleno para el texto &quot;Cuadrado&quot;
c.drawString(125, 80, &quot;Cuadrado&quot;)

#Dibujamos un Círculo
c.setFillColorRGB(0.8, 0.0, 0.2)
c.circle(205, 205, 100, stroke=1, fill=1)  # x, y, radio, stroke, fill
c.setFillColorRGB(0, 1, 0.2)
c.drawString(155, 200, &quot;Circulo&quot;)

#Dibujamos una Elipse
c.setStrokeColorRGB(1, 0, 0.0)
c.ellipse(75, 450, 350, 335)  #x1, y1, x2, y2, stroke, fill
c.setFillColorRGB(0, 0, 0.5)
c.drawString(150, 375, &quot;Elipse&quot;)

c.showPage()  # Finalizamos la página

#Si lo han notado hemos de ingresar color de relleno y trazo para cada forma,
#sino especificamos, lo hara en negro.
#grid(lista en x, lista en y)
c.grid([20,40,60,80], [alto-20,alto-40,alto-60,alto-80])
#arc(x1,y1,x2,y2)
c.arc(200, 200, 400, 400)
#rect(x, y, alto, ancho, stroke=1, fill=0)
c.rect(300,500, 200, 100)

#Veamos los tipos de dibujo de texto
c.line(ancho/2, 720, ancho/2, 640)
c.drawString(ancho/2, 700, &quot;Texto con punto de referencia a la izquierda&quot;)
c.drawRightString(ancho/2, 680, &quot;Texto con punto de referencia a la derecha&quot;)
c.drawCentredString(ancho/2, 660, &quot;Texto con punto de referencia en el centro&quot;)

c.save()  # Archivamos y cerramos canvas
os.system(&quot;test.pdf&quot;)  # Lanzamos el pdf
&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/01/reportlab-pdfgen-formas-basicas-y-texto.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoa0NHff3ob4SPWDZ1qvoXPhUNc6kMcceAlOoFF9aRcHs5IZ7SnpR7UvGUTOC85gmF4xusO2i_qTvw9jURZ5rLouYfhTkRBfNBuRNB_g21rcmhCEcJnJmZHFmMl6jcSaA52H7NabAiCBE/s72-c/Screenshot_7.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-7691416080334148998</guid><pubDate>Fri, 31 Jan 2014 22:07:00 +0000</pubDate><atom:updated>2014-01-31T17:07:36.179-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">PDF</category><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: pdfgen - Lo básico de Canvas (01)</title><description>PDFGEN es la interfaz más baja para generar PDF. Son secuencias de instrucciones para pintar un documento sobre una secuencia de páginas. El objeto que provee tal operación de pintado es el pdfgen canvas.&lt;br /&gt;&lt;br /&gt;El canvas debe ser considerado como un papel con coordenadas x, y cuyo punto de origen es la esquina inferior izquierda. Se incrementa a la derecha y hacia arriba.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT0Aq6j1bXdKnfTNYCkhb853Z90Hvfyzg5F4DJGMcfm9zbpU-9mzBk5NjQ91h-PoXq-uTSWnsSiIb7aF8L1NxvS0VRS5oVzsbxvLMQx4JSteBr1l-4jvLQafYAyl6I3z2X5PzHUQhzCHM/s1600/Screenshot_4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT0Aq6j1bXdKnfTNYCkhb853Z90Hvfyzg5F4DJGMcfm9zbpU-9mzBk5NjQ91h-PoXq-uTSWnsSiIb7aF8L1NxvS0VRS5oVzsbxvLMQx4JSteBr1l-4jvLQafYAyl6I3z2X5PzHUQhzCHM/s1600/Screenshot_4.png&quot; height=&quot;320&quot; width=&quot;233&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Hay que tener en cuenta que ReportLab tiene tres formas de uso (APIs): Canvas, Platypus, y Drawing.&lt;br /&gt;
Canvas te permitira dibujarlo todo en la hoja, Platypus va más enfocado en la producción de texto, separando el formato del contenido (algo similar a html y css), Drawing te permitirá crear gráficos un poco más avanzados, como los estadísticos.&lt;br /&gt;
&lt;br /&gt;
Veamos un ejemplo básico:
&lt;pre class=&quot;brush: py;&quot;&gt;
import os

# Importamos Librería a usar
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4  # Puede ser también Letter, A5, A6, ...

#A4 es una tupla, podemos extraer sus valores
#ancho, alto = A4 como también de la siguiente forma
anchoHoja = A4[0]
altoHoja = A4[1]
print anchoHoja, altoHoja

#Creamos el contexto de Canvas
#- Creamos el nombre del archivo 
#- pagesize es una tupla, por eso le pasamos A4 de lib
c=canvas.Canvas(&quot;test.pdf&quot;, pagesize = A4)

#Escribimos en la primera hoja
#drawString(x,y, texto)
c.drawString(50,500, &quot; Mi PRIMER PDF&quot;)
c.drawString(250,300,&quot;Coordenada=(250,300) &quot;)
c.drawString(350,200,&quot;(350, 10)&quot;)
c.drawString(150,400,&quot;Aprendiendo REPORTLAB&quot;)

#Grabamos la página presente del canvas
c.showPage()  

#Escribimos en la segunda hoja
c.drawString(50,500, &quot;Segunda Hoja&quot;)
c.showPage()

#Archivamos y cerramos el canvas
c.save()  

#Lanzamos el pdf creado
os.system(&quot;test.pdf&quot;)

&lt;/pre&gt;</description><link>http://menteleal.blogspot.com/2014/01/reportlab-pdfgen-lo-basico-de-canvas-01.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT0Aq6j1bXdKnfTNYCkhb853Z90Hvfyzg5F4DJGMcfm9zbpU-9mzBk5NjQ91h-PoXq-uTSWnsSiIb7aF8L1NxvS0VRS5oVzsbxvLMQx4JSteBr1l-4jvLQafYAyl6I3z2X5PzHUQhzCHM/s72-c/Screenshot_4.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-21149989086510835</guid><pubDate>Fri, 31 Jan 2014 21:49:00 +0000</pubDate><atom:updated>2014-01-31T16:50:44.398-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">PDF</category><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">ReportLab</category><title>ReportLab: Libreria PDF para Python (00)</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvNQxYqBP9E9v3ofCF-x_wkSqvTQ5ZtDAZOSzyv4fJJ6pcOVty8Rc6sqbUbDAO2aq0xD2lVd_g3eWPDjYlC3xmzntr6amjdChD7V0r8QVQnMz7WdAVOjKXx9z-UKAbo7guH9Z7BCty4OI/s1600/ReportLabLogo.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvNQxYqBP9E9v3ofCF-x_wkSqvTQ5ZtDAZOSzyv4fJJ6pcOVty8Rc6sqbUbDAO2aq0xD2lVd_g3eWPDjYlC3xmzntr6amjdChD7V0r8QVQnMz7WdAVOjKXx9z-UKAbo7guH9Z7BCty4OI/s1600/ReportLabLogo.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
ReportLab, es una libreria que permite crear directamente documentos en PDF (Formato de Documento Portable) usando Python como lenguaje de programación. También permite crear gráficos en bitmap y vectores.&lt;br /&gt;
&lt;br /&gt;
Me interese sobre ReportLab, debido a su capacidad de generar reportes, ya en el trabajo solicitan crear cantidad de reportes para ser impresos y hacerlo llegar a los clientes. Python es uno de mis lenguajes favoritos, y ReportLab me llamo mucho la atención.&lt;br /&gt;
&lt;br /&gt;
ReportLab, actualmente trabaja con Python 2.7, por lo que la versión 3, tendrá que esperar (talvez este sea uno de los motivos por lo que soy renuente a desechar el 2.7)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Instalación:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Consultar en la página oficial &lt;a href=&quot;http://www.reportlab.com/software/installation/&quot;&gt;http://www.reportlab.com.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Tanto en Linux como en windows hay que instalar dos cosas: primero, el ReportLab, y segundo, &lt;a href=&quot;http://www.pythonware.com/products/pil/&quot;&gt;PIL&lt;/a&gt; (Python Imaging Library). Este último es para poder usar imágenes png o gif.&lt;br /&gt;
&lt;b&gt;&amp;nbsp; &lt;/b&gt;&lt;br /&gt;
&lt;b&gt;1. Linux&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
En ambos paquetes aplicar los siguientes comandos para instalar:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
python setup.py build&lt;br /&gt;
sudo python setup.py install&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;2. Windows&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Los instaladores lo pueden descargar desde la página oficial, o si desean les dejo estos enlaces:&lt;br /&gt;
&lt;a href=&quot;https://www.dropbox.com/sh/lvh2qx21guu0w8l/p1CT6lG5ur/PIL-1.1.7.win32-py2.7.exe&quot;&gt;PIL&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.dropbox.com/s/6ewh8atfbe8tpqj/reportlab-daily.win32-py2.7.exe&quot;&gt;ReportLab 2.7&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Los manuales en español son inexistentes, solo hay pocas páginas web que lográn tal cometido;sin embargo todo se halla en la &lt;a href=&quot;http://www.reportlab.com/docs/reportlab-userguide.pdf&quot;&gt;guía de usuario&lt;/a&gt;, que para muchos les puede incomodar el lenguaje anglosajon en el cual esta escrito. Sea el caso, trataré de publicar información sobre los aspectos generales de Report Lab, y lo más extremo, será cuestión de consultar en la guía oficial.</description><link>http://menteleal.blogspot.com/2014/01/reportlab-libreria-pdf-para-python-00.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvNQxYqBP9E9v3ofCF-x_wkSqvTQ5ZtDAZOSzyv4fJJ6pcOVty8Rc6sqbUbDAO2aq0xD2lVd_g3eWPDjYlC3xmzntr6amjdChD7V0r8QVQnMz7WdAVOjKXx9z-UKAbo7guH9Z7BCty4OI/s72-c/ReportLabLogo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-2161503242152257328</guid><pubDate>Wed, 29 Jan 2014 16:08:00 +0000</pubDate><atom:updated>2014-01-29T11:08:45.743-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">cairo</category><category domain="http://www.blogger.com/atom/ns#">python</category><title>Nuestro propio widget con PyCairo</title><description>Estos días estaba jugando con Cairo, debido a la curiosidad de saber de como hacen aquellos widgets que no encuentras en un editor de interfaz. Un ejemplo es el ecualizador de Clementine.&lt;br /&gt;
&lt;br /&gt;
En fin, hay muchas formas de hacerlo, y Cairo me llamo la atención, ya que se integra con Python y GTK. Mi idea fue crear un progress bar algo distinto (sólo con fines de probar), en el cuál si cargaba hasta el 50% se mostrara en rojo, si cargaba hasta el 80% se mostrara en amarillo y el resto en azul. Y al completarse todo la carga, se muestre un texto &quot;100% completo&quot; sobre un fondo degradado:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjqPg5rNOnSMXQG5BEyZT4vXyiwhLwlJ5EzOPZjjvvnxinXtoRXPYOm4B5iH2mdtJfVKme4UtFykM0PBrS7lFJQN4n3eRnEMcn7q9pj9cke5O3w50rl_XdUr4rJCH2tUWuY80eoY8YDTk/s1600/Screenshot_1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjqPg5rNOnSMXQG5BEyZT4vXyiwhLwlJ5EzOPZjjvvnxinXtoRXPYOm4B5iH2mdtJfVKme4UtFykM0PBrS7lFJQN4n3eRnEMcn7q9pj9cke5O3w50rl_XdUr4rJCH2tUWuY80eoY8YDTk/s1600/Screenshot_1.png&quot; height=&quot;80&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHN2oJrcRoRLpvhqIvA9wiM_YRpLPmJeY-43LIbI330m3ObOavYKwDdoVbeIgXQRMPI4CYmuHBsZvzCh-vc_4sXoxsvY6JFfFHbLAIC534OEyFTlDRxsJMrNDhBh-DZaZ9W2a-tX7PaRA/s1600/Screenshot_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHN2oJrcRoRLpvhqIvA9wiM_YRpLPmJeY-43LIbI330m3ObOavYKwDdoVbeIgXQRMPI4CYmuHBsZvzCh-vc_4sXoxsvY6JFfFHbLAIC534OEyFTlDRxsJMrNDhBh-DZaZ9W2a-tX7PaRA/s1600/Screenshot_2.png&quot; height=&quot;81&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Para ello trabaje, no enrrollandome con puro código gtk para crear una ventanita, sino usando glade.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikBzq0M-h9lZiSg6gfMleNOAoxg9SUvA61HKJrSWLDftws0qbOnt9vOs51-3RVvrokon6fhRYDbaXxuljXn_i0i3At8bsddwdanG26MWl5uCtrWo6EFA5Yro81M50dDDk6zO_zATFVNKQ/s1600/Screenshot_3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikBzq0M-h9lZiSg6gfMleNOAoxg9SUvA61HKJrSWLDftws0qbOnt9vOs51-3RVvrokon6fhRYDbaXxuljXn_i0i3At8bsddwdanG26MWl5uCtrWo6EFA5Yro81M50dDDk6zO_zATFVNKQ/s1600/Screenshot_3.png&quot; height=&quot;271&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Aquí use aquella herramienta que no había usado hasta ahora, el drawingarea.&lt;br /&gt;
&lt;br /&gt;
Bueno el código quedó de la siguiente&amp;nbsp; forma:&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;#!/usr/bin/python
# -*- coding: utf-8 -*- 
import gtk
import glib
import cairo


class App(object):
    def __init__ (self):
        #Iniciamos el porcentaje de carga
        self.percent = 0
        
        #Se carga el archivo glade
        builder = gtk.Builder()
        builder.add_from_file(&#39;Final.ui&#39;)
        
        #Se recuperan los widget a usar
        self.winMain = builder.get_object(&#39;window1&#39;)
        self.drawingarea = builder.get_object(&#39;drawingarea1&#39;)
        
        #Instanciamos nuestro widget
        self.pbBGR = ProgressBarBGR(self.drawingarea)
        
        #Conectamos las señales y mostramos la ventana
        builder.connect_signals(self)
        self.winMain.show()
    
    def on_btnIniciar_clicked(self, *args):
        #Ejecutamos el mètodo cada 20ms
        glib.timeout_add(20, self.on_timer) 
        
    def on_timer(self):
        #Incrementamos el porcentaje
        self.percent += 1
        
        #Trabajamos con nuestro widget
        self.pbBGR.setPercent(self.percent) # INSERTAMOS PORCENTAJE
        self.pbBGR.draw()  # DIBUJAMOS
        
        if self.percent &amp;gt; 99:
            self.percent = 0
            return False
        return True


class ProgressBarBGR():
    def __init__(self, drawingarea):
        self.__percent = 0  # Ocultamos nuestra variable
        self.drawingarea = drawingarea
        self.drawingarea.connect(&quot;expose-event&quot;, self.expose)
        
    def setPercent(self, percent):
        self.__percent = percent
        
    def getPercent(self):
        return self.__percent
    
    def draw(self):
        self.drawingarea.queue_draw()

    def expose(self, widget, event):
        #Creamos el contexto       
        cr = widget.window.cairo_create()
        
        #Determinamos eje x, eje y, ancho y alto del área de dibujo
        x, y = event.area.x, event.area.y
        width, height = event.area.width, event.area.height

        #Dibujamos el rectángulo principal
        cr.set_line_width(2)
        cr.rectangle(x, y, width, height)
        cr.set_source_rgb(0, 0, 0)
        cr.fill()
        
        #Dibujamos los 100 rectángulos y ponemos colores
        h = height
        w = width / 100.0
        perc = self.getPercent()
        if perc &amp;gt; 0:
            for i in range(0,100):
                if i &amp;lt;= perc and i &amp;lt; 50:
                    cr.set_source_rgb(1, 0, 0)
                elif i &amp;lt;= perc and i &amp;gt;= 50 and i &amp;lt;=80:
                    cr.set_source_rgb(1, 1, 0)
                elif i &amp;lt;= perc and i &amp;gt; 80 and i &amp;lt;=99:
                    cr.set_source_rgb(0, 0.5, 0.9)
                else:
                    cr.set_source_rgb(0, 0, 0)
                cr.rectangle( w * i, 0, w -1, h)
                cr.fill()
                
        #Dibujamos la barra completada al 100%
        if perc == 100:
            #Degradamos
            lg = cairo.LinearGradient(x, y, x, height)
            lg.add_color_stop_rgba(0.1, 0, 0, 0, 1)
            lg.add_color_stop_rgba(0.5, 0, 0.6, 1, 1)
            lg.add_color_stop_rgba(0.9, 0, 0, 0, 1)
            
            cr.rectangle(x, y, width, height)
            cr.set_source(lg)
            cr.fill()
            
            #Insertamos el texto de 100%
            cr.select_font_face(&quot;Serif&quot;, cairo.FONT_SLANT_NORMAL, 
            cairo.FONT_WEIGHT_BOLD)
            if height &amp;lt; 100:
                cr.set_font_size( height/2.5)
            else:
                cr. set_font_size((width + height) / 20)
            texto = &quot;100% COMPLETO&quot;
            (x, y, txtwidth, txtheight, dx, dy) = cr.text_extents(texto)
            cr.set_source_rgb(0.5, 0.5, 0.5)
            cr.move_to(width/2 - txtwidth/2, h/2 + txtheight/2)
            cr.show_text(texto)
            cr.set_source_rgb(1, 1, 1)
            cr.move_to(width/2 - txtwidth/2 + 2, h/2 + txtheight/2 +2 )
            cr.show_text(texto)
            
        
if __name__ == &quot;__main__&quot;:
    App()
    gtk.main()
&lt;/pre&gt;
&lt;br /&gt;
PD: esto fue desarrollado con PyGTK, facilmente se puede cambiar el código a PyGI. Por ejemplo:&lt;br /&gt;
en vez de usar&amp;nbsp; &quot;expose-event&quot; se podría usar &quot;draw&quot;. Es cuestión de revisar la documentación.</description><link>http://menteleal.blogspot.com/2014/01/nuestro-propio-widget-con-pycairo.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjqPg5rNOnSMXQG5BEyZT4vXyiwhLwlJ5EzOPZjjvvnxinXtoRXPYOm4B5iH2mdtJfVKme4UtFykM0PBrS7lFJQN4n3eRnEMcn7q9pj9cke5O3w50rl_XdUr4rJCH2tUWuY80eoY8YDTk/s72-c/Screenshot_1.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-4790428307578964351</guid><pubDate>Tue, 28 Jan 2014 22:54:00 +0000</pubDate><atom:updated>2014-01-29T10:18:27.647-05:00</atom:updated><title>Test SyntaxHighlighter</title><description>Estaba haciendo algunas pruebas con SyntaxHighlighter para publicar código con resaltadores de texto, el cuál es relativamente fácil de instalar.

Se puede hacer de dos formas:&lt;br /&gt;
&lt;br /&gt;
1. La primera es descargarse los archivos desde la página &lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/download/&quot;&gt;http://http://alexgorbatchev.com/SyntaxHighlighter/download/&lt;/a&gt;, y subirlos junto a nuestro web. Tenemos que poner esto en la cabecera:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;&quot;&gt;&lt;link href=&quot;styles/shCoreDefault.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;&gt;&lt;/link&gt;
&lt;script src=&quot;scripts/shCore.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/shBrushPython.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/shBrushCss.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;SyntaxHighlighter.all();&lt;/script&gt;
&lt;/pre&gt;
2. Se puede enlazar desde el servidor del autor de la siguiente forma:

&lt;br /&gt;
&lt;pre class=&quot;brush:xml;&quot;&gt;&lt;link href=&quot;http://alexgorbatchev.com/pub/sh/current/styles/shCoreDefault.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;&gt;&lt;/link&gt;
&lt;script src=&quot;http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js&quot; type=&quot;text/javascript&quot;&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js&quot;&gt;
&lt;script type=&quot;text/javascript&quot;&gt;SyntaxHighlighter.all();&lt;/script&gt;
&lt;/pre&gt;
Luego donde insertemos el código, podemos hacerlo con la etiqueta pre o script, pero se ha de usar la clase de la siguiente forma:
&lt;br /&gt;
&lt;pre class=&quot;brush:xml;&quot;&gt;
&lt;pre class=&quot;brush: xml;&quot;&gt;    
&lt;section&gt;
        &lt;p&gt;Ahora se muestra el código resaltado &lt;/p&gt;
&lt;/section&gt;
&lt;/pre&gt;
&lt;/pre&gt;
Soporta una gran cantidad de lenguajes, solo es cuestión de añadir el archivo js en el head.
Además cuenta con &lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/manual/themes/&quot;&gt;temas.&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;
Por ejemplo aquí muestro código en python:
&lt;br /&gt;
&lt;pre class=&quot;brush:py;&quot;&gt;#!/usr/bin/python
# -*- coding: utf-8 -*- 
import gtk
import glib
import cairo

class App(object):
    def __init__ (self):
        #Variables Iniciales
        self.percent = 0
        
        # Se carga el archivo glade con la ventana
        builder = gtk.Builder()
        builder.add_from_file(&#39;Final.ui&#39;)
        
        # Se recuperan los widget a usar (no son necesarios todos)
        self.winMain = builder.get_object(&#39;window1&#39;)
        self.drawingarea = builder.get_object(&#39;drawingarea1&#39;)
        self.pbBGR = ProgressBarBGR(self.drawingarea)  # INSTANCIAMOS
        
        # Se asocian las señales
        builder.connect_signals(self)
        self.winMain.show()


&lt;/pre&gt;
</description><link>http://menteleal.blogspot.com/2014/01/blog-post.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-5179790542471307176</guid><pubDate>Sat, 11 Jan 2014 16:46:00 +0000</pubDate><atom:updated>2014-01-11T11:46:17.369-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gtk</category><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">threads</category><title>gtk.gdk.thread_init() cuelga el programa en Windows XP (SOLUCIONADO)</title><description>Cuando usamos gtk.gdk.thread_init() con python todo parece genial, corre en plataformas Linux y Windows, pero en este último, no lo hace en todas sus versiones. Hay empresas que hasta el día de hoy siguen usando Windows XP, y es aquí cuando nuestro programa crashea.&lt;br /&gt;
&lt;br /&gt;
La solución es simple, y consultando en el IRC, en vez de usar gtk.gdk.thread_init(), hemos de usar:&lt;br /&gt;
&lt;div class=&#39;terminal&#39;&gt;import gobject&lt;br&gt;gobject.thread_init()&lt;/div&gt;
&lt;br /&gt;
Con ello podremos correr nuestros hilos sin problemas :)</description><link>http://menteleal.blogspot.com/2014/01/gtkgdkthreadinit-cuelga-el-programa-en.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8895950188245720481.post-1563300682209425495</guid><pubDate>Fri, 10 Jan 2014 16:29:00 +0000</pubDate><atom:updated>2014-01-10T11:46:26.801-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">py2exe</category><category domain="http://www.blogger.com/atom/ns#">python</category><title>Evitar el log file generado por py2exe</title><description>&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsdRBxBgmVbgD6hyphenhypheny37XDtZOZu3Lz7nqycImFupBPBHCXCaJXLl0502aoRtvhprVewiA7B0wXTgDaAkQawbldv2XcqGlYYyV_l6gluJXShwVOqlWkgLXjzYp3su-MmVBpZTv4mBgbizOs/s1600/pythonlogo.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsdRBxBgmVbgD6hyphenhypheny37XDtZOZu3Lz7nqycImFupBPBHCXCaJXLl0502aoRtvhprVewiA7B0wXTgDaAkQawbldv2XcqGlYYyV_l6gluJXShwVOqlWkgLXjzYp3su-MmVBpZTv4mBgbizOs/s1600/pythonlogo.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Para los que usamos py2exe para crear ejecutables en windows, nos habremos dado cuenta en algún momento, que si nuestro aplicativo cae en error, automaticamente se crea un archivo *.exe.log y se muestra en una ventana similar a esta:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTeCYQFfZAs3c-pPIUYGJTtu91DuPKL7wm6ND_CKhbrjCTDQt7Q1Ino3VFihnsYPV1tkM3yWXjR-gd8TzSqi4LZSLm-OfjTfYv3-JdYVz3T3kwEOk4M44ldE6puGzt06LBelmwUgdRRmY/s1600/Screenshot_10.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTeCYQFfZAs3c-pPIUYGJTtu91DuPKL7wm6ND_CKhbrjCTDQt7Q1Ino3VFihnsYPV1tkM3yWXjR-gd8TzSqi4LZSLm-OfjTfYv3-JdYVz3T3kwEOk4M44ldE6puGzt06LBelmwUgdRRmY/s1600/Screenshot_10.png&quot; height=&quot;124&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Esto para el usuario final suele ser molestoso sobre todo cuando nuestro programa no presenta error alguno, sino &quot;advertencias&quot; que se pueden generar por distintas causas.&lt;br /&gt;
&lt;br /&gt;
Una solución que encontré, fue la de agregar las siguientes lineas en el archivo principal, (que por lo general es el archivo &quot;scripts&quot; del cual creamos el ejecutable .exe, por ejemplo main.py)&lt;br /&gt;
&lt;div class=&quot;terminal&quot;&gt;
import sys&lt;br /&gt;
sys.stderr = sys.stdout
&lt;/div&gt;
&lt;br /&gt;
Pero, qué es lo que hace estas líneas?&lt;br /&gt;
&lt;br /&gt;
Bueno, en aplicaciones de interfaz gráfica, py2exe redirecciona sys.stderr a un log file, pero como aqui le pasamos sys.stdout lo que hará es ignorar todo lo escrito. Esto no quiere decir que desaparece los errores o advertencias del programa, solo los oculta del GUI. En el setup.py podemos crear un debug con la opción console, y asi siempre ver los errores en linea de comandos y evitarnos el fastidio de tal ventanita.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://menteleal.blogspot.com/2014/01/evitar-el-log-file-generado-por-py2exe.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsdRBxBgmVbgD6hyphenhypheny37XDtZOZu3Lz7nqycImFupBPBHCXCaJXLl0502aoRtvhprVewiA7B0wXTgDaAkQawbldv2XcqGlYYyV_l6gluJXShwVOqlWkgLXjzYp3su-MmVBpZTv4mBgbizOs/s72-c/pythonlogo.png" height="72" width="72"/><thr:total>0</thr:total></item></channel></rss>