Seite 1 von 1

Tkinter erste animationen

Verfasst: Donnerstag 27. Dezember 2012, 16:43
von BerryBlue
Hallo Pythonforum,

Nach einigem rumprobieren mit Tkinter (python 2.7) schaff ich es einfach nicht, ein Bild einzufügen und dieses nach einer gewissen Zeit, ohne das man irgendeinen Knopf drückt das bild wechselt, also ein neues drübergezeichnet wir.

Wäre sehr dankbar über Lösungsvorshlage bzw. hilfen und Ideen.

MFG BerryBlue

PS: also sowas wie Animationen

Re: Tkinter erste animationen

Verfasst: Donnerstag 27. Dezember 2012, 16:47
von BlackJack
@BerryBlue: Man nimmt sich ein Widget welches ein Bild darstellen kann, zum Beispiel ein `Label` und benutzt die `after()`-Methode um das Bild durch ein anderes zu ersetzen.

Re: Tkinter erste animationen

Verfasst: Donnerstag 27. Dezember 2012, 16:52
von BerryBlue
Vielen dank für die schnelle Antwort, könnten Sie mir aber bitte ein Beispiel geben, da ich es iw. nicht verstehen.

MFG BerryBlue

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 00:01
von StefanLawl

Code: Alles auswählen

after(ms,func[,argl[,..]])

Code: Alles auswählen

Bein.after(1000, treten)
Auto.after(20, bremsen)
Computer.after(340, ausschalten)
Label.after(500, ...
:mrgreen:

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 11:35
von wuf
Hi BerryBlue

Hier eine konkrete Idee:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk

class App(object):
    
    def __init__(self):
        self.win = tk.Tk()
        self.win.protocol("WM_DELETE_WINDOW", self.close)

    def projector(self):
        if self.picture_pointer == len(self.pictures):
            self.picture_pointer = 0
            
        self.picture_display.config(image=self.pictures[self.picture_pointer])
            
        self.picture_pointer += 1
        
        self.win.after(PAUSE, self.projector)
        
    def run(self):
        self.win.mainloop()
    
    def close(self):
        self.win.destroy()

APP_WIN_XPOS = 50
APP_WIN_YPOS = 50
SCRIPT_NAME = sys.argv[0]

IMAGES = ['Bild_01.gif', 'Bild_02.gif']
PAUSE = 500  # Milliseconds
    
app = App()
app.win.title(SCRIPT_NAME)
app.win.geometry('+{0}+{1}'.format(APP_WIN_XPOS, APP_WIN_YPOS))

app.pictures = [tk.PhotoImage(file=image) for image in IMAGES]
app.picture_pointer = 0

app.picture_display = tk.Label(app.win)
app.picture_display.pack()

app.projector()

app.run()
Gruß wuf :wink:

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 11:57
von BlackJack
@wuf: Da ist jetzt aber einiges auf Modulebene was eigentlich in die `__init__()` gehört.

Und die Bahandlung von 'WM_DELETE_WINDOW' ist überflüssig solange man nicht noch etwas anderes dort machen möchte als nur das Fenster zu zerstören. Das passiert auch so.

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 12:38
von Sirius3
ein schönes Beispiel für itertools:

Code: Alles auswählen

from itertools import cycle
[...]
    def projector(self):
        self.picture_display.config(image=self.pictures.next())
        self.win.after(PAUSE, self.projector)
[...]
app.pictures = cycle(tk.PhotoImage(file=image) for image in IMAGES)
Grüße
Sirius

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 13:38
von wuf
OK BlackJack

Habe das Skript nach deinen Anregungen angepasst und den Tipp von Sirius3 einfliessen lassen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from itertools import cycle

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk

class App(object):
    
    def __init__(self, images):
        self.win = tk.Tk()
        self.win.geometry('+{0}+{1}'.format(APP_WIN_XPOS, APP_WIN_YPOS))
        self.win.protocol("WM_DELETE_WINDOW", self.close)
        self.win.title(SCRIPT_NAME)
        
        #self.pictures = [tk.PhotoImage(file=image) for image in images]
        self.pictures = cycle(tk.PhotoImage(file=image) for image in images)
        #self.picture_pointer = 0

        self.picture_display = tk.Label(self.win)
        self.picture_display.pack()

    #def projector(self):
        #if self.picture_pointer == len(self.pictures):
            #self.picture_pointer = 0
            
        #self.picture_display.config(image=self.pictures[self.picture_pointer])
            
        #self.picture_pointer += 1
        
        #self.win.after(PAUSE, self.projector)

    def projector(self):
        self.picture_display.config(image=self.pictures.next())
        self.win.after(PAUSE, self.projector)
                
    def run(self):
        self.win.mainloop()
    
    def close(self):
        print('Good Bye')
        self.win.destroy()

APP_WIN_XPOS = 50
APP_WIN_YPOS = 50
SCRIPT_NAME = sys.argv[0]

IMAGES = ['Bild_01.gif', 'Bild_02.gif']
PAUSE = 500  # Milliseconds
    
app = App(IMAGES)
app.projector()
app.close_button = tk.Button(app.win, text='Schliessen', command=app.close)
app.close_button.pack()
app.run()
BlackJack hat geschrieben:Und die Bahandlung von 'WM_DELETE_WINDOW' ist überflüssig solange man nicht noch etwas anderes dort machen möchte als nur das Fenster zu zerstören. Das passiert auch so.
Das nehme ich bei meinen Skripts als Standard rein im Falle man doch auf die Idee kommt vor der Vorhangschliessung des Auftritts noch etwas auszuführen.

@Sirius3: Danke für deinen Tipp mit der Methode 'cycle' des Moduls 'itertools'. Funktioniert unter Python 2.6 bestens aber unter Python 3.x wird folgende Exception geworfen:
Traceback (most recent call last):
File "label_dia_images_02.py", line 58, in <module>
app.projector()
File "label_dia_images_02.py", line 40, in projector
self.picture_display.config(image=self.pictures.next())
AttributeError: 'itertools.cycle' object has no attribute 'next'
Gruß wuf :wink:

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 13:50
von BlackJack
@wuf: Iteratoren haben in Python 3 keine `next()`-Methode mehr, dafür gibt es eine `next()`-Funktion. Die gibt es schon ab Python 2.6, also wenn Du keine ältere Version unterstützen möchtest, kann man die entsprechende Zeile einfach so ändern:

Code: Alles auswählen

self.picture_display.config(image=next(self.pictures))
Edit: Da der OP Python 2.7 einsetzt ist das aber eigentlich auch kein Problem von Sirius3 sondern von Deiner zusätzlichen Anforderung, dass es auch mit Python 3 laufen soll.

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 13:50
von yipyip
@wuf:
(Python 3.3)

Code: Alles auswählen

>>> from itertools  import cycle
>>> seq = range(3)
>>> cs = cycle(seq)
>>> cs.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'itertools.cycle' object has no attribute 'next'
>>> next(cs)
0
>>> next(cs)
1
>>> next(cs)
2
>>> next(cs)
0
>>> cs.__next__()
1
>>> cs.__next__()
2
...
Siehe auch:
http://python3porting.com/differences.html#next

:wink:
yipyip

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 16:23
von wuf
Hi BlackJack & yipyip

Danke für eure hilfreichen Antworten und Links. Habe das Skript somit auf den neuesten Stand für Py2.6 plus und Py3.x gebracht:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from itertools import cycle

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk

class App(object):
    
    def __init__(self, images):
        self.win = tk.Tk()
        self.win.geometry('+{0}+{1}'.format(APP_WIN_XPOS, APP_WIN_YPOS))
        self.win.protocol("WM_DELETE_WINDOW", self.close)
        self.win.title(SCRIPT_NAME)
        
        self.pictures = cycle(tk.PhotoImage(file=image) for image in images)

        self.picture_display = tk.Label(self.win)
        self.picture_display.pack()

    def projector(self):
        self.picture_display.config(image=next(self.pictures))
            
        self.win.after(PAUSE, self.projector)
                
    def run(self):
        self.win.mainloop()
    
    def close(self):
        print('Good Bye')
        self.win.destroy()

APP_WIN_XPOS = 50
APP_WIN_YPOS = 50
SCRIPT_NAME = sys.argv[0]

IMAGES = ['Bild_01.gif', 'Bild_02.gif']
PAUSE = 500  # Milliseconds
    
app = App(IMAGES)
app.projector()
app.close_button = tk.Button(app.win, text='Schliessen', command=app.close)
app.close_button.pack()
app.run()
BlackJack hat geschrieben:Edit: Da der OP Python 2.7 einsetzt ist das aber eigentlich auch kein Problem von Sirius3 sondern von Deiner zusätzlichen Anforderung, dass es auch mit Python 3 laufen soll.
Ist jetzt natürlich klar. Sorry an Sirius3 sollte er mich hier missverstanden haben.

Gruß wuf :wink:

Edit: Habe die Fallunterscheidung von 'next' für Python2.x & 3.x korrigiert.

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 18:27
von yipyip
@wuf:
Du brauchst doch gar keine Fallunterscheidung mit try...except zu machen. Die 'next(<iterator>)' Funktion gibts doch fuer Python 2.6+ sowie Python 3 (wie BlackJack schon sagte).
Jetzt laeufts auch mit Python 2.5- !? :-)

:wink:
yipyip

Re: Tkinter erste animationen

Verfasst: Freitag 28. Dezember 2012, 20:55
von wuf
Danke yipyip

Da habe ich BlackJack falsch verstanden. Setzte das Modul 'itertools' bis jetzt noch nie ein. Das vereinfacht das Skript natürlich noch mehr.

Gruß wuf :wink: