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
canvas-diagramm speichern
Hi pyzip
Hier eine Variante mit PIL:Gruss wuf
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()
Take it easy Mates!
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
Gruß Rainer
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
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
Take it easy Mates!
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
Danke und Gruß, Rainer
Code: Alles auswählen
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')
Danke Rainer
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::
Gruss wuf
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
Take it easy Mates!
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
Gruß Rainer
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
Gruß Rainer
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
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
Take it easy Mates!
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
Gruß Rainer
OK. Funktioniert das folgende Skript bei dir ohne Fehlermeldungen und was zeigt es auf dem Monitor?
Gruss wuf
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()
Take it easy Mates!
Funktioniert das folgende zweite Skript auch ohne Fehlermeldungen? Was siehst du jetzt auf deinem Monitor?
Grss wuf
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()
Take it easy Mates!
@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.
@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.
Hi Sirius3
Danke für deine Unterstützen.
Gruss wuf
Danke für deine Unterstützen.
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.@wuf: Pakete, die man als lokaler Nutzer installiert, werden unter ~/.local/lib/python... abgelegt. Das ist also ganz normal.
Gruss wuf
Take it easy Mates!
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
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