[python-users] canvas export nach svg

Thomas Lenarz tommesml at netcologne.de
Do Jun 25 19:13:31 CEST 2009


Andreas schrieb:
> Ich brauch zwar nur einen abgeänderten Teil deiner Zeichenoberfläche, 
> erweitert um die 'export_as_svg' methode (korrekt angeschlossen), jedoch 
> speichert es mir die Farbinformationen der Canvasobjekte nicht mit ab 
> (den Rest schon). Hab die Lösung leider bisher nicht finden können, da 
> ich mich mit dem svg Format kaum auskenne.

Hallo Andi,

vielen Dank erst einmal für Deine Anfrage. Es ist schön zu wissen, dass 
sich noch jemand anders mit den gleichen Dingen beschäftigt :-)

Farben (außer schwarz) habe ich ja bisher mehr oder weniger konsequent 
ignoriert. Es ist tatsächlich aber recht einfach.

Die Canvas-Objekte kennen (je nach Objekttyp etwas unterschiedlich) die 
beiden Optionen fill und outline. SVG hingegen kennt fill und stroke 
(siehe auch: http://www.w3.org/TR/SVG11/shapes.html#RectElement). Ich 
habe jedoch den Eindruck, dass fill aus TK-Canvas-Sicht nicht immer auch 
zwangsläufig fill aus SVG-Sicht bedeutet. Je nach Objekttyp wird man 
outline auf stroke oder fill auf stroke abbilden müssen.

Ich habe das Ganze einmal wie folgt im Graphrenderer ausprobiert:

Ich habe alle Linien des Graphen einmal versuchsweise blau gezeichnet 
und dann beim Erzeugen der Objekt-Enumeration aus dem Canvas jeweils die 
Option fill mit ausgelesen (mit itemcget() ).

Beim Erzeugen des SVG Outputs habe ich dann diesen Wert direkt in das 
neu erzeugte Attribut "stroke" zur polyline hinzugefügt.

Wenn man sich das SVG danach anschaut, sind tatsächlich auch hier alle 
Linien blau.

Das ist natürlich zunächst einmal nur die "naive" Methode. Sie geht 
davon aus, dass alle Farbnamen aus TK auch gleich in SVG vorhanden sind. 
Muss ja nicht unbedingt so sein, so dass man hier ggf. noch eine 
Übersetzungstabelle braucht. Ich habe trotzdem das Gefühl, dass man 
hiermit schon einmal weit kommen kann.

Es folgen noch meine Source-Änderungen im Detail (siehe jeweils den 
Marker "<--- here"):

Würde mich freuen zu hören, ob Du damit weiterkommst :-)

Viele Grüße
Thomas


linien.py:

		self.line=self.c.create_line( x1, y1, x2, y2,
                             #arrow="both",
                             fill="blue",                     <--- here
                             joinstyle="round")
                             #width="5")
                             #arrowshape="180 80 10")

zeichenflaeche.py:

     def enumerate_elements( self ):
         """
             Aufzaehlen aller Elemente auf der Zeichenflaeche
         """

         # Ermittle aktuelle Ausdehnung der Zeichnung
         # (kann auch negative Koordination enthalten).
         x1,y1,x2,y2 = self.c.cget("scrollregion").split()

         elements = self.c.find_all()
         for el in elements:
             # x und y Koordination so verschieben, dass
             # sie nicht negativ sind. (::2: Jedes zweite Element)
             coord_x = [ x - float(x1) for x in self.c.coords(el)[0::2] ]
             coord_y = [ y - float(y1) for y in self.c.coords(el)[1::2] ]

             coords = list(zip(coord_x, coord_y) )

             # pyId-Tag ermitteln
             tags=self.c.gettags(el)
             for tag in tags:
                 if tag.startswith("pyid"):
                     pyid_tag = tag
                     break;

             if self.c.type(el) != "text":
                 yield (pyid_tag, self.c.type(el) ,coords, 
self.c.itemcget(el, "fill" )  )                <--- here (*** Farbe ist 
hierdurch im  Tupel am Index 3 vorhanden ***)
             else:
                 yield (pyid_tag, self.c.type(el) ,coords, 
self.c.itemcget(el, "text" ), self.c.itemcget(el, "fill" ))    <--- here


graphrenderer_frame.py:

def export_as_svg()

...

         template5 = Template( '<polyline points="$points" 
stroke="$stroke" />\n' )    <--- here

...

             if element[1] == "line":
                 points = ""
                 for one_point in element[2]:
                     points = points + str(one_point[0]) + "," + 
str(one_point[1]) + " "
                 f.write( template5.substitute( points=points, 
stroke=element[3] ) )       <--- here

...









Mehr Informationen über die Mailingliste python-users