Das Script auf dieser Seite lief zwar bereits zufriedenstellend und für erste
Testzwecke war es und ist es immer noch geeignet, doch im Funktionsumfang sehr begrenzt. Zwischenzeitlich
wurde es nicht, wie eigentlich geplant, überarbeitet, sondern völlig neu geschrieben. Der grundlegende Aufbau
und Ablauf blieb erhalten, so dass es auch heute noch für erste Schritte als Einstieg genutzt werden kann.
Wer im Anschluss daran etwas tiefer einsteigen möchte, in die Entwicklung einer App für 2D Animationen mit
Python und PIL, dem sei das kleine Projekt mit einem erweiterten Script empfohlen:
» Tkinter App: 2D Animationen für Sequenzen und Movie Szenen «
Beispiel:
Ansicht des Tkinter Widget-Fensters beim Start einer simplen Animation.
Mit "deepcopy" wird eine Copy des Background-Images erzeugt, in der ein oder mehrere
Objekte mit "paste" eingefügt werden. Das ursprüngliche Background-Image wird dabei nicht verändert.
Bei jedem Fortschreiten mit der "after" Methode verändert sich nicht nur der Zählerstand, sondern auch die
xy-Position der Image-Objekte.
Code des ersten Animation-Scripts:
from tkinter import Tk, Frame, Label, Button, Checkbutton, Radiobutton, IntVar from PIL import Image, ImageTk from copy import deepcopy class SimpleAnimation: """Eine Klasse für simple 2D Animationen mit Image-Objekten""" def __init__(self, im_bg = None, im_01 = None, im_02 = None): self.fenster = Tk() self.fenster.title("Simple Animationen") self.fenster.wm_iconbitmap("logo.ico") self.fenster.config(bg = "#808080") self.auswahl = IntVar() # Auswahl Ein/Aus für Speicherung self.laufmal = IntVar() # Für Auswahl mit Radiobuttons vier_buttons = {"50":50, "100":100, "150":150, "200":200} # Aufteilung in oberen und unteren Frame mit Buttons usw. self.frame_o = Frame(self.fenster, bg = "#808080", padx = 10) self.frame_u = Frame(self.fenster, bg = "#6f6352", padx = 10) self.fenbild = Label(self.frame_o, bd = 0) self.control = Label( self.frame_u, bd = 4, bg = "#000", fg = "#40ff40", width = 20, relief = "sunken", pady = 4) self.checker = Checkbutton( self.frame_u, text = "Mit Speicherung?", bg = "#6f6352", fg = "#ecb200", selectcolor = "#606060", variable = self.auswahl, command = self.setzeAuswahl) self.starter = Button( self.frame_u, text = "Start", font = ("cambria", 10, "bold"), padx = 12, command = self.bewegeObjekte) # Labels und Buttons im Fenster anordnen (packen) self.frame_o.pack(side = "top") self.fenbild.pack(padx = 20, pady = 20) self.frame_u.pack(side = "bottom", fill = "x") self.control.pack(side = "left", padx = 20, pady = 4) self.checker.pack(side = "left", padx = 2, pady = 4) for key, wert in vier_buttons.items(): radiobb = Radiobutton( self.frame_u, text = key, bg = "#6f6352", fg = "#e2aa00",selectcolor = "#606060", variable = self.laufmal, value = wert, command = self.setzeAuswahl) radiobb.pack(side = "left") self.starter.pack(side = "left", padx = 2, pady = 4) # Images vor und nach dem Öffnen self.iopen_bg = im_bg # Die zu öffnende Hintergrundgrafik self.iopen_01 = im_01 # Die zu öffnenden Image-Objekt-Dateien, self.iopen_02 = im_02 # falls vorhanden. self.image_bg = None # Die geöffnete Hintergrundgrafik self.image_01 = None # Die geöffneten Image-Objekt-Dateien, self.image_02 = None # falls vorhanden. self.label_bg = None # Die fürs Label zusammengefügten Images self.img_temp = None # Die temporären Image-Dateien # Positionen bei Start und bei Veränderungen self.posx_01 = 0 self.posy_01 = 0 self.posx_02 = 0 self.posy_02 = 0 self.startwt = 0 # Der Startwert bei Aufruf und Durchlauf self.endwert = 0 # Der Endwert bis Ende der Animation self.speichg = 0 # Für Speicherung, Defaultwert ist False self.bildnum = 0 # Die laufende Bildnummer def main(self, px01 = None, py01 = None, px02 = None, py02 = None): if self.iopen_bg is not None: self.image_bg = Image.open(self.iopen_bg) if self.iopen_01 is not None: self.image_01 = Image.open(self.iopen_01).convert("RGBA") if self.iopen_02 is not None: self.image_02 = Image.open(self.iopen_02).convert("RGBA") if px01 is not None: self.posx_01 = px01 if py01 is not None: self.posy_01 = py01 if px02 is not None: self.posx_02 = px02 if py02 is not None: self.posy_02 = py02 # Aufruf zum Positionieren beim Öffnen des Fensters. if self.iopen_bg is not None: self.positioniereObjekte() else: self.fenbild.config(text = "Fehler beim Laden von Images!", bg = "#808080", fg = "#ffc949") def positioniereObjekte(self): self.img_temp = deepcopy(self.image_bg) # Die bewegten Objekte in jeder Runde neu ausrichten. if self.iopen_01 is not None: self.img_temp.paste( self.image_01, (self.posx_01,self.posy_01), self.image_01) # Falls _01 nicht vorhanden, so kann _02 nicht folgen. if self.iopen_02 is not None: self.img_temp.paste( self.image_02, (self.posx_02,self.posy_02), self.image_02) # Speichern aller Einzelbilder einer Animation if self.speichg == True: print(self.speichg) self.bildnum += 1 ablage = "temps/temp-{0:03d}.png".format(self.bildnum) self.img_temp.save(ablage, "PNG") # Nur ausführen, wenn wenigsten _bg vorhanden ist. if self.iopen_bg is not None: self.label_bg = ImageTk.PhotoImage(self.img_temp) self.fenbild.config(image = self.label_bg) def bewegeObjekte(self): if self.startwt < self.endwert: self.fenster.after(400, self.bewegeObjekte) self.startwt += 1 # Berechnung der Bahnen self.posy_01 += 1 self.posy_02 += 1 if self.startwt < 110: self.posx_01 += 1 self.posx_02 -= 1 # Aufruf zum Positionieren bei laufender Animation. self.positioniereObjekte() # Als Anzeige der laufenden Werte ausg = "{0:d} - {1:d} | ".format(self.posx_01,self.posy_01) ausg += "{0:d} - {1:d} | ".format(self.posx_02,self.posy_02) ausg += "E {0:d}".format(self.endwert) self.control["text"] = ausg def setzeAuswahl(self): self.endwert = self.laufmal.get() self.speichg = self.auswahl.get() # --- Instanziieren eines Objektes der Klasse SimpleAnimation --------- objekt00 = "images/background.jpg" objekt01 = "images/kugel-01.png" objekt02 = "images/kugel-02.png" if __name__ == "__main__": instanz = SimpleAnimation(objekt00, objekt01, objekt02) instanz.main(10,10,308,10) instanz.fenster.mainloop()
Weiterlesen: 2D-Animationen » new «
Einstieg in Python
OOP mit Python
Codes & Tutorials
Kleines Projekt