Seite 1 von 2
canvas-diagramm speichern
Verfasst: Freitag 16. März 2018, 20:51
von pyzip
Hallo, habe vor einiger Zeit unter dem Betreff "errechnete Werte in Canvas anzeigen" gute Hilfe und berechtigte Kritik bekommen. Einer der Kritikpunkte war, dass ich die Diagrammdaten "wild" im Code verstreut hatte. Habe nun etwas Zeit und wollte mein Diagramm nun etwas universeller gestalten. Ein wichtiger Punkt für mich wäre, dass ich das fertige Diagramm abspeichern kann. Wahrscheinlich sehe ich den Wald vor lauter Bäumen nicht, aber ich finde keine Funktion, die so etwas macht. Alles was ich finde, bezieht sich auf Diagramme aus Matplotlib. Vielleicht kann ich einen Tip bekommen, wonach oder wo ich suchen muß.
Vielen Dank und Gruß, Rainer
Re: canvas-diagramm speichern
Verfasst: Sonntag 18. März 2018, 03:34
von pyzip
Liebe Leute, ich weiß zwar nicht, ob das der richtige Weg ist, aber keine Hilfe???
Re: canvas-diagramm speichern
Verfasst: Sonntag 18. März 2018, 12:00
von Sirius3
@pyzip: tkinters Canvas sieht nur vor, den Inhalt als postscript mit der gleichnamigen Funktion zu speichern.
Re: canvas-diagramm speichern
Verfasst: Sonntag 18. März 2018, 18:07
von pyzip
@Sirius3: Danke! Damit habe ich wenigstens ein paar Beispiele gefunden, mit denen ich spielen kann.
Rainer
Re: canvas-diagramm speichern
Verfasst: Montag 19. März 2018, 12:44
von wuf
Hi pyzip
Hier eine Variante mit PIL:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import math
try:
# Tkinter for Python 2.xx
import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
import tkinter as tk
from PIL import Image, ImageDraw, ImageFont, ImageTk
APP_TITLE = "Save Canvas Image"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 500
APP_HEIGHT = 400
GRAPH_TITLE = "sin(x)=blue cos(x)=red"
GRAPH_WIDTH = 400
GRAPH_HEIGHT = 300
GRAPH_TITLE_FONT = ImageFont.truetype("arial.ttf", 18)
GRAPH_FILE_NAME = "My_Graph.jpg"
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
CENTER_Y = GRAPH_HEIGHT / 2
INCREMENT_X = 1
FACTOR_X = 0.04
AMPLITUDE = 80
class MyGraph(tk.Frame):
def __init__(self, app_win, width, height, **kwargs):
self.app_win = app_win
self.width = width
self.height = height
tk.Frame.__init__(self, app_win, **kwargs)
self.build()
def build(self):
self.draw_frame = tk.Label(self)
self.draw_frame.pack(fill='both', expand=True)
self.graph_plane = Image.new("RGB", (self.width, self.height), WHITE)
self.drawing = ImageDraw.Draw(self.graph_plane)
self.calculate()
self.label_image = ImageTk.PhotoImage(self.graph_plane)
self.draw_frame['image'] = self.label_image
def calculate(self):
sine_values = list()
for x in range(400):
x_coords = x * INCREMENT_X
y_coords = int(math.sin(x * FACTOR_X) * AMPLITUDE) + CENTER_Y
sine_values.append((x_coords, y_coords))
cos_values = list()
for x in range(400):
x_coords = x * INCREMENT_X
y_coords = int(math.cos(x * FACTOR_X) * AMPLITUDE) + CENTER_Y
cos_values.append((x_coords, y_coords))
self.draw_graph(sine_values, cos_values)
self.graph_plane.save(GRAPH_FILE_NAME)
def draw_graph(self, sin_values, cos_values):
self.drawing.line(sin_values, fill=BLUE)
self.drawing.line(cos_values, fill=RED)
self.drawing.text(
(10, 20), GRAPH_TITLE, fill=BLACK,font=GRAPH_TITLE_FONT)
def main():
app_win = tk.Tk()
app_win.title(APP_TITLE)
app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
app = MyGraph(app_win, GRAPH_WIDTH, GRAPH_HEIGHT
).pack(fill='both', expand=True)
app_win.mainloop()
if __name__ == '__main__':
main()
Gruss wuf

Re: canvas-diagramm speichern
Verfasst: Montag 19. März 2018, 18:05
von pyzip
Hi wuf, danke für den ausführlichen Code! Ich erinnere mich, dass du mir seinerzeit schon einmal das Modul "PIL" vorgeschlagen hast. Ich hatte da aber erhebliche Schwierigkeiten und nach der Hilfe eines Mod. hat das Anzeigen der Zwischenergebnisse in einem Canvas dann ja geklappt. Werde aber trotzdem dein Beispiel durcharbeiten...hoffentlich mit etwas mehr Erfolg als damals...stehe nun ja nicht mehr ganz am Anfang.
Gruß Rainer
Re: canvas-diagramm speichern
Verfasst: Montag 19. März 2018, 19:03
von wuf
Hi pyzip
Wenn du eine Grafik erstellst die anschliessend auch als Bilddatei gespeichert werden muss würde ich an Stelle eines
Tk.Canvas-Widgets die
Draw-Klasse des
Pil-ImageDraw Moduls verwenden. Diese Klasse verfügt über genügend Methoden um eine saubere Grafik zu konstruieren. Die Grafik wird dann nur im Speicher erstellt. Um diese Grafik danach aus dem Speicher in einem
Tk-Widget anzuzeigen muss sie mittels der
PhotoImage-Methode des
Pil-ImageTk Moduls in das
Tk-Bildformat umgewandelt werden. Dann eignet sich das
tk.Label-Widget für die einfache Anzeige der Grafik am besten. Du kannst die Grafik natürlich auch in einem
tk.Canvas-Widget mittels der
canvas.create_image-Methode anzeigen. Um die Grafik anschliessend in einer Datei mit einem gewünschten Bildformat zu speichern bedient man sich der
save-Methode des
Pil-Image-Objektes.
Gruss wuf

Re: canvas-diagramm speichern
Verfasst: Montag 19. März 2018, 21:57
von pyzip
Hi wuf, danke für deine weiteren Ausführungen. Mein Problem war, in einem Diagramm jeweils Zwischenergebnisse einer Berechnung anzuzeigen. Es geht erst in 2ter Linie darum, ein fertiges Diagramm zu speichern. Es muß auch mit meiner Randbedingung erzeugt werden. Und genau das hat dein Beispiel nicht gebracht. Der Code, den ich damals bekommen habe, macht das alles schon perfekt und nun will ich zum Schluss auch noch das Diagramm abspeichern. Möglichst so, dass ich es später einfach per Standard-Viewer ansehen kann! Muß mich aber noch ausgiebig mit deinem Vorschlag auseinander setzen.
Danke und Gruß, Rainer
Re: canvas-diagramm speichern
Verfasst: Donnerstag 22. März 2018, 20:24
von pyzip
Hi Wuf, habe noch eine Schwierigkeit mit deinem Script...mein PIL kennt kein ImageTk und ich bekomme immer eine Fehlermeldung:
File "/usr/lib/python3/dist-packages/PIL/ImageFont.py", line 238, in truetype
return FreeTypeFont(font, size, index, encoding)
File "/usr/lib/python3/dist-packages/PIL/ImageFont.py", line 127, in __init__
self.font = core.getfont(font, size, index, encoding)
OSError: cannot open resource
...kann aber nichts damit anfangen. Habe verschiedene Fonts versucht, aber nichts geht.
@ Sirius3, hallo, dass mit postscript habe ich versucht. Habe ein Beispiel gefunden.
Code: Alles auswählen
def safe(self)
ps = self.canvas.postscript(colormode='color')
img = Image.open(io.BytesIO(ps.encode('utf-8')))
img.save(path+'test.jpg')
Es funktioniert, aber das Ergebnis ist ein grottenschlechtes Bild! Mach' ich da was falsch und lohnt es sich da weiter zu forschen??
Danke Rainer
Re: canvas-diagramm speichern
Verfasst: Donnerstag 22. März 2018, 23:28
von wuf
Hi pyzip
a)
Kannst du einmal nachschauen ob das
PIL ImageTk-Modul auf deinem Gerät überhaupt installiert ist? Es sollte sich unter folgendem Pfad befinden:
/usr/lib/python3/dist-packages/PIL/ImageTk.py
Wenn das
PIL ImageTk-Modul nicht auffindbar ist musst du es nachinstallieren.
b)
Das Skript findet auf deinem Gerät eventuell meine verwendete Font-Resource
ImageFont.truetype("arial.ttf", 18) nicht. Die verschiedenen Truetype Font-Resourcen befinden sich auf meinem Gerät unter:
/usr/share/fonts/truetype/
Ein Beispiel aus der PIL-Beschreibung "Python Imaging Library (PIL)" von John W. Shipman (NMT) um einen Truetype-Font in das Skript zu laden::
Code: Alles auswählen
fontPath = "/usr/share/fonts/dejavu-lgc/DejaVuLGCSansCondensed-Bold.ttf"
sans16 = ImageFont.truetype ( fontPath, 16
Gruss wuf

Re: canvas-diagramm speichern
Verfasst: Freitag 23. März 2018, 17:11
von pyzip
Hi Wuf, danke. Natürlich ist das Modul PIL ImageTk-Modul nicht da...habe mich nur gewundert, dass "Image, ImageDraw und ImageFont" da sind! Werde gleich mal versuchen, das ImageTK-Modul zu installieren. Und das Beispiel aus der PIL-Beschreibung "Python Imaging Library (PIL)" werde ich auch probieren. Hoffentlich klappts.
Gruß Rainer
Re: canvas-diagramm speichern
Verfasst: Freitag 23. März 2018, 18:12
von pyzip
Hi Wuf, habe mal nach ImageTk.py gesucht und in /home/ich/.local/lib/python3.5/site-packages/PIL/ImageTk.py gefunden. Ich vermute mal, dass ich das File nicht einfach kopieren und in /usr/lib/python3/dist-packages/PIL/ einfügen kann. Bin etwas ratlos...
Gruß Rainer
Re: canvas-diagramm speichern
Verfasst: Freitag 23. März 2018, 20:22
von wuf
Hi pyzip
Ich nehme an das Verzeichnis
PILexistierte bereits unter dem Pfad
/usr/lib/python3/dist-packages/? und du hast es sicher nicht von Hand erstellt? Das Modul PIL Image.Tk würde ich nur mit einem Paketmanager erstellen. Bei mir habe ich es mit der
Synaptic-Paketverwaltung mit dem Namen python3-pil.imagetk installiert. Du kannst es auch über das Terminal mit
sudo apt-get install python3-pil.imagetk installieren. Aber auf keinen Fall das Modul von Hand herum kopieren! Für mich ist es eher ungewohnt, dass Python unter dem Heimverzeichnis
/home/BENUTZER/.local/lib/python3.5/ installiert ist.
Gruss wuf

Re: canvas-diagramm speichern
Verfasst: Freitag 23. März 2018, 20:54
von pyzip
Hi Wuf, danke. Bevor ich irgendwas mache...ich habe Ubuntu-Studio-17... und ich habe natürlich "nichts gemacht"! Das Verzeichnis PIL existiert bereits unter dem Pfad /usr/lib/python3/dist-packages/...und wenn ich versuche ImageTk zu installieren, bekomme ich ominöse Fehlermeldungen, die ich so interpretiere: für mein Python 3. gibt es kein ImageTk. Ist leider alles sehr verwirrend! Sorry und danke für deine Geduld.
Gruß Rainer
Re: canvas-diagramm speichern
Verfasst: Freitag 23. März 2018, 21:10
von wuf
OK. Funktioniert das folgende Skript bei dir ohne Fehlermeldungen und was zeigt es auf dem Monitor?
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tkinter as tk
from PIL import Image, ImageDraw, ImageFont, ImageTk
APP_TITLE = "Save Canvas Image"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 500
APP_HEIGHT = 400
class MyGraph(tk.Frame):
def __init__(self, app_win, **kwargs):
self.app_win = app_win
tk.Frame.__init__(self, app_win, **kwargs)
def main():
app_win = tk.Tk()
app_win.title(APP_TITLE)
app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
app = MyGraph(app_win, bg='yellow').pack(fill='both', expand=True)
app_win.mainloop()
if __name__ == '__main__':
main()
Gruss wuf

Re: canvas-diagramm speichern
Verfasst: Freitag 23. März 2018, 21:50
von wuf
Funktioniert das folgende zweite Skript auch ohne Fehlermeldungen? Was siehst du jetzt auf deinem Monitor?
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tkinter as tk
from PIL import Image, ImageDraw, ImageFont, ImageTk
APP_TITLE = "Save Canvas Image"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 500
APP_HEIGHT = 400
WHITE = (255, 255, 255)
class MyGraph(tk.Frame):
def __init__(self, app_win, **kwargs):
self.app_win = app_win
tk.Frame.__init__(self, app_win, **kwargs)
self.graph_plane = Image.new("RGB", (200, 200), WHITE)
self.drawing = ImageDraw.Draw(self.graph_plane)
self.label_image = ImageTk.PhotoImage(self.graph_plane)
self.draw_frame = tk.Label(self, image=self.label_image)
self.draw_frame.pack(expand=True)
def main():
app_win = tk.Tk()
app_win.title(APP_TITLE)
app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
app = MyGraph(app_win, bg='steelblue').pack(fill='both', expand=True)
app_win.mainloop()
if __name__ == '__main__':
main()
Grss wuf

Re: canvas-diagramm speichern
Verfasst: Samstag 24. März 2018, 03:36
von Sirius3
@wuf: Pakete, die man als lokaler Nutzer installiert, werden unter ~/.local/lib/python... abgelegt. Das ist also ganz normal.
@pyzip: Du hast irgendwann ImageTk lokal installiert. DA Du keine Fehlermeldungen gepostet hast, kann man nicht sagen, warum das bei Dir nicht funktioniert. Erster Schritt wäre immer, bei Python-Modulen mit vielen Abhängigkeiten, diese über den Paketmanager Deiner Linuxdistribution zu installieren.
Re: canvas-diagramm speichern
Verfasst: Samstag 24. März 2018, 09:11
von wuf
Hi Sirius3
Danke für deine Unterstützen.
@wuf: Pakete, die man als lokaler Nutzer installiert, werden unter ~/.local/lib/python... abgelegt. Das ist also ganz normal.
Wusste ich noch nicht. Python habe ich bis jetzt noch nie lokal installiert da ich der einzige Benutzer des Systems bin. Bei einer Neuinstallation von Ubuntu wird Python ohnehin automatisch Systemweit angelegt. Zusätzliche Pakete installierte ich dann meistens über einer Paketverwaltung, welche immer Legitimation als Administrator verlangte. Spezielle Pakete die nicht mit Hilfe einer Paketverwaltung installierbar waren habe ich dann aus einem Terminal mit
sudo pythonx setup.py PAKET nachinstalliert. Ich vermute, dass bei unserem Kollegen pyzip etwas mit den
Umgebungsvariablen nicht stimmt.
Gruss wuf

Re: canvas-diagramm speichern
Verfasst: Samstag 24. März 2018, 16:18
von pyzip
Hallo, danke. @Wuf: ich habe deinen Code in Spider gestartet und bekomme natürlich diese Fehlermeldung:
runfile('/home/zip/py/nn/diagramm_pil_2.py', wdir='/home/zip/py/nn')
Traceback (most recent call last):
File "<ipython-input-1-4c6bb4b0f268>", line 1, in <module>
runfile('/home/zip/py/nn/diagramm_pil_2.py', wdir='/home/zip/py/nn')
File "/home/zip/.local/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "/home/zip/.local/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "/home/zip/py/nn/diagramm_pil_2.py", line 9, in <module>
from PIL import Image, ImageDraw, ImageFont, ImageTk
ImportError: cannot import name 'ImageTk'
Und @Sirius3: Ich habe immer einen User unter Ubuntu laufen und ich habe bisher immer mit pip bzw. mit pip3 installiert. Das sollte doch keine Probleme bereiten oder bringt sudo etwa die Vermischung von "Systemweit" und User? Bin aber echt überfordert!
Gruß Rainer
Re: canvas-diagramm speichern
Verfasst: Samstag 24. März 2018, 16:35
von Sirius3
@pyzip: Du hast ja auch ImageTk für Python 3.5 installiert und startest das Programm mit Python 3.6.