Canvas-Grafiken weiterbearbeiten

Fragen zu Tkinter.
Antworten
tomdest
User
Beiträge: 12
Registriert: Donnerstag 3. Januar 2008, 19:49

Hallo Forum,

Dank eurer Hilfe bin ich jetzt VIEL weiter.

Das folgende Programm ist bis auf die Fehlerabfragen recht weit:

Code: Alles auswählen

#-*- coding: cp1252 -*-
#UVSim 1.0
#simuliert UV/Vis-Spektren aus Daten von quantenchemischen Programmen, d. h.
#aus Wertepaaren Lambda / Oszillatorstärke wird das entsprechende "Strichspektrum" und eines aus
#addierten Gauß-Funktionen berechnet

import Tkinter
import tkMessageBox
import tkFileDialog
import math

#Variablen setzen / initialisieren

Pi=3.1415
DatenDa=False
#allgemeine Funktionen
def Achsen():
    global Pixelratio   
    global Welle_min
    global xLauf
    for Teil in cnvGrafik.find_all():   #Löschen des Canvas
        cnvGrafik.delete(Teil)     
    Pfeilxx=10.0   #x-Achse x-Inkrement für Pfeilspitze
    Pfeilxy=5.0    #zeichnet Achsen, Beschriftung, Skalierung
    Pfeilyx=5.0
    Pfeilyy=10.0
    x1=0.0
    y1=0.0
    x2=0.0
    y2=0.0
    Strich=4.0       #halbe Strichlänge auf der x-Achse
    Welle_min=0.0
    Welle_max=0.0
    Differenz=0.0
    Welle_max=sclLambdamax.get()
    Welle_min=sclLambdamin.get()
    Differenz=Welle_max-Welle_min
    Teiler=200.0
    if Differenz < 1000:
        Teiler=50.0                                     #Einteilung x-Achse
    if Differenz < 500:
        Teiler=20.0
    if Differenz < 200:
        Teiler=10.0
    if Differenz < 100:
        Teiler=5.0
    
    x1=45; y1=410; x2=45; y2=10                       #y-Achse
    cnvGrafik.create_line(x1,y1,x2,y2, fill="yellow")
    x1=45; y1=10; x2=45 - Pfeilyx; y2=10 + Pfeilyy
    cnvGrafik.create_line(x1,y1,x2,y2, fill="yellow")
    x1=45; y1=10; x2=45 + Pfeilyx; y2=10 + Pfeilyy
    cnvGrafik.create_line(x1,y1,x2,y2, fill="yellow")
    
    x1=45; y1=410; x2=565; y2=410                     #x-Achse
    cnvGrafik.create_line(x1,y1,x2,y2, fill="yellow")
    x1=565; y1=410; x2=565 - Pfeilxx; y2=410 + Pfeilxy
    cnvGrafik.create_line(x1,y1,x2,y2, fill="yellow")
    x1=565; y1=410; x2=565 - Pfeilxx; y2=410 - Pfeilxy
    cnvGrafik.create_line(x1,y1,x2,y2, fill="yellow")
    
    cnvGrafik.create_text(250, 437, text="Wellenlänge [/nm]", fill="yellow")   #Achsenbeschriftung
    cnvGrafik.create_text(15, 40, text="rel.", fill="yellow")
    cnvGrafik.create_text(15, 55, text="Abs.", fill="yellow")
    
    Lauf=Welle_min
    xLauf=65.0
    Pixelratio=500.0/Differenz
    xPixel=Teiler*Pixelratio
    while Lauf<Welle_max:
        cnvGrafik.create_line(xLauf, 410-Strich, xLauf, 410+Strich, fill="yellow")
        cnvGrafik.create_text(xLauf, 410+2*Strich, text=int(Lauf), fill="yellow")
        xLauf=xLauf+xPixel
        Lauf=Lauf+Teiler
    xLauf=65.0
    
def Oszillatoren():             #zeichnet f-Striche
    if DatenDa==False:
        return
    Pixelratio_f=200.0          #400 Pixel für die gesamt Y-Achse
    for l in xrange(Datenmenge):
        x_f=(xLauf + Pixelratio * (Peak[l] - Welle_min))
        y_f=(410 - Oszillator[l] * Pixelratio_f)
        if (x_f > 45) and (x_f < 565):  #Überprüfung, ob noch im Rahmen der x-Achse
            cnvGrafik.create_line(x_f, 410, x_f, y_f, fill="lightblue")
 
def Spektrum():
    if DatenDa==False:
        return
    Alphawert=sclAlphawerte.get()
    Alpha=[0,0,0,0]
    Spektrumhoehe=sclHoehe.get()
    #Welle_min=sclLambdamin.get()
    #Pixelratio= 2.0 #Vorschlag
    Flag=False
    i=46.0
    x1=0.0
    y1=0.0
    x2=0.0
    y2=0.0
    y_vorher=0.0
    while i<565.0:
        Wert = 0.0
        for l in xrange(Datenmenge):
            Alpha[l] = 0.2 / Alphawert
            aktWelle = Welle_min + (i - 65) / Pixelratio;
            Wert = Wert + math.sqrt(Alpha[l] / Pi) * Oszillator[l] * Spektrumhoehe * math.exp(-Alpha[l] * (aktWelle - Peak[l])**2)
        if Flag==False:
            Flag=True
            x1=i
            y1=410
            x2=i
            y2=410-Wert
        else:
            x1=i-1
            x2=i
            y1=y2
            y2=410-Wert
        cnvGrafik.create_line(x1,y1,x2,y2, fill="red");
        Haupt.update_idletasks()
        i=i+1
def Zeichnen(event):
    Achsen()
    Oszillatoren()
    Spektrum()   
#Ende allgemeine Funktionen

#Menüpunktfunktionen
def Menuepunkt_Hilfe():
    Text="1.) Zuerst Datei öffnen\n2.) Dann Menüpunkt 'XYZ' wählen\n3.) Datei speichern\n4.) Programm beenden"
    tkMessageBox.showinfo("Hilfe",Text )
def MenuePunkt_Ueber():
    tkMessageBox.showinfo("Über...", "UVSim für Python (c) 2008 Dr. Thomas Gareis, Version 1.0")
def MenuePunkt_Oeffnen():
    global Datenmenge
    global Peak
    global Oszillator
    global DatenDa
    Dateiname=tkFileDialog.askopenfilename(title="Datei öffnen...", defaultextension="*.uvs", filetypes=[("UVSim-Dateien","*.uvs")])
    Datei=file(Dateiname, "r")
    for i in range(2):      #2 Kommentarzeilen unbeachtet lassen
        Datei.readline()
#Zeile einlesen, am Tabulator splitten, 2. Wert nehmen ([0] =1. Wert), von Formatierungszeichen befreien
    Datenmenge=int(Datei.readline().split("\t")[1].strip()) 
    
    for i in range(2):      #2 Kommentarzeilen unbeachtet lassen
        Datei.readline()
    Puffer=Datei.readlines()
    Datenpunkte=len(Puffer)
    Peak=range(Datenmenge)
    Oszillator=range(Datenmenge)
    if Datenpunkte==Datenmenge:  #Vergleich Datenzeilen = Datenpunkte mit der Datenmenge
        DatenDa=True
        print "scheint korrekt..."
    else:
        DatenDa=False
        print "Fehler beim Einlesen: Datenpunkte stimmen nicht mit der Datenmenge überein!"
    for i in range(Datenmenge):
        Peak[i]=round(float(Puffer[i].split("\t")[0].strip()),1)
        Oszillator[i]=round(float(Puffer[i].split("\t")[2].strip()),2)   #dritter Wert, da 2 Tabulatoren
    Datei.close()
def MenuePunkt_Speichern():
    if DatenDa==False:
        return
    Dateiname=tkFileDialog.asksaveasfilename(title="Datei speichern...", defaultextension="*.uvs", filetypes=[("UVSim-Dateien","*.uvs")])
    Datei=file(Dateiname,"w")
    Datei.write("Ausgabefile von UvSim (c) Dr. Thomas Gareis\n\n")
    Datei.write("Datenmenge:\t"+str(Datenmenge)+"\n\n")
    Datei.write("Lambda [/nm]\tOszillatorstärke\n")
    for i in range(Datenmenge):
        Datei.write(str(Peak[i])+"\t\t"+str(Oszillator[i])+"\n")
    Datei.close()

def MenuePunkt_Ende():
    Antwort=tkMessageBox.askokcancel("Programm beenden", "Sind Sie sicher?")
    if Antwort==True:
        Haupt.quit()

#Ende der Menüpunktfunktionen


#GUI
 #Hauptfenster installieren
Haupt=Tkinter.Tk()
Haupt.title("UVSim für Python Version 1.0") 
Haupt.geometry("800x600")
 #Installation des Menüs
Menueleiste=Tkinter.Menu(master=Haupt)
Haupt.config(menu=Menueleiste)

MenueDatei=Tkinter.Menu(master=Menueleiste)
MenueDatei.add_command(label="Datei öffnen", command=MenuePunkt_Oeffnen)
MenueDatei.add_command(label="Datei speichern", command=MenuePunkt_Speichern)
MenueDatei.add_separator()
MenueDatei.add_command(label="Ende", command=MenuePunkt_Ende)
Menueleiste.add_cascade(label="Datei", menu=MenueDatei)

MenueHilfe=Tkinter.Menu(master=Menueleiste)
MenueHilfe.add_command(label="Hilfe", command=Menuepunkt_Hilfe)
MenueHilfe.add_separator()
MenueHilfe.add_command(label="Über...", command=MenuePunkt_Ueber)
Menueleiste.add_cascade(label="Hilfe", menu=MenueHilfe)
 #Ende Menü
 #Zeichenfläche, eingebettet in einen Rahmen
fraRahmen=Tkinter.Frame(Haupt, relief="raised", borderwidth="1")
cnvGrafik=Tkinter.Canvas(fraRahmen, width="585", height="457", bg="blue")
 #vier SCale-Widgets zum Einstellen der Parameter
sclAlphawerte=Tkinter.Scale(Haupt, orient="horizontal", label="Varianz Alphawerte", from_="1", to="300", command=Zeichnen) 
sclHoehe=Tkinter.Scale(Haupt, orient="horizontal", label="Varianz Höhe", from_="2000", to="6000", command=Zeichnen) 
sclLambdamin=Tkinter.Scale(Haupt, orient="horizontal", label="Lambda, min.", from_="150", to="499", command=Zeichnen) 
sclLambdamax=Tkinter.Scale(Haupt, orient="horizontal", label="Lambda, max.", from_="500", to="1000", command=Zeichnen) 
 #Widgets anzeigen
fraRahmen.grid(column="1", row="0", columnspan="5", sticky="nsew")
cnvGrafik.grid()
sclAlphawerte.grid (column="2", row="2",sticky="ew")
sclHoehe.grid (column="4", row="2",sticky="ew")
sclLambdamin.grid (column="2", row="3",sticky="ew")
sclLambdamax.grid (column="4", row="3",sticky="ew")
#Ende GUI



#Start Hauptschleife Tk-Fenster    
Haupt.mainloop()
Als Testdatei zum Öffnen kann man das Folgende z. B. unter "Daten.uvs" abspeichern:
http://test.drgareis.de/Daten1.uvs

Alles getestet unter Win XP: Datei öffnen => irgendeinen Schieberegler betätigen => Spektrum!

So weit, so gut, nun meine Frage:

Wie kann ich die Canvasgrafik weiterbearbeiten, also z. B. in die Zwischenablage kopieren bzw. als BMP-Datei o.ä. speichern?


Viele Grüße,


Tom
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Wie kann ich die Canvasgrafik weiterbearbeiten, also z. B. in die Zwischenablage kopieren bzw. als BMP-Datei o.ä. speichern?
Zunächst einmal gar nicht. Tkinter bietet von Hause aus nur die Möglichkeit, den Canvas-Inhalt als Postscript-Datei abzuspeichern.

Wenn dir das nicht reicht:
Die Python Imaging Library PIL bietet meines Wissens (aber da kennen sich andere besser aus) hier Möglichkeiten.

Oder: Du kannst aus dem Script heraus ein externes Screenshot-Programm verwenden, das mit entsprechenden Parametern aufgerufen den Bildschirm "knipst".
Gregor Lingl beschreibt in seinem Buch "Python für Kids" eine Möglichkeit, wie das mit IrfanView funktioniert.
tomdest
User
Beiträge: 12
Registriert: Donnerstag 3. Januar 2008, 19:49

1.) Danke!
2.) Mist (wegen Tkinter!)

Viele Grüße,


Tom
Antworten