Seite 1 von 1

Rekursion abbrechen ++

Verfasst: Samstag 4. Oktober 2008, 22:20
von Janux
Hallo!
Der Text aus dem Entry soll blinkend dargestellt werden. Wenn jedoch
danach ein weiterer Text eingegeben wird überlagert sich die aktuelle
'self.blink' Funktion mit der neuen. Meine 'Lösung' ist, dass erst 4 sec
nach dem 'weiter' das Blinken beginnt.

Code: Alles auswählen

import Tkinter as tk

class Gui():
    
    k = 0
    
    def __init__(self):
        self.root = tk.Tk()
        self.entry = tk.Entry(self.root)
        self.entry.pack()
        self.text = tk.StringVar()
        self.label = tk.Label(self.root, textvariable=self.text)
        self.label.pack()
        self.button = tk.Button(self.root, text='Weiter', command=self.setLabel)
        self.button.pack(side=tk.BOTTOM)

        self.root.minsize(150,100)
        self.root.mainloop()
        
    def setLabel(self):
        self.k = 1
        
        def prozedur():
            self.k = 0
            self.blink()
        self.root.after(4000, prozedur)
        
    def blink(self, n=0):
        # Set default pause value after first call.
        # Than recursion with n = 1 or n = 2
        # Pause ever-growing up to ca. 3500 ms
        
        if self.k:
            return
        
        if n == 0:
            self.pause = 500
            self.runde = 1
            self.blink(1)
        if n == 1:
            self.text.set(self.entry.get())
            self.root.after(1250, self.blink, 2)
        if n == 2:
            self.text.set('')
            if self.pause < 3000:
                self.pause += 75 * self.runde
                self.runde += 1
            self.root.after(self.pause , self.blink, 1)

a = Gui()
Es wäre schön wenn ihr mir helfen könnt. Ansonsten muss ich mir diese
Funktion mit dem Modul KThread (Kill a Thread with Python...) hintricksen. :?

Verfasst: Sonntag 5. Oktober 2008, 08:39
von kaytec
Hallo Janux !

Code: Alles auswählen


import Tkinter as tk

class Gui():
   
    def __init__(self):
        self.blocked = False
        self.counter = 0
        self.root = tk.Tk()
        self.entry = tk.Entry(self.root)
        self.entry.pack()
        self.text = tk.StringVar()
        self.label = tk.Label(self.root)
        self.label.pack()
        self.button = tk.Button(self.root, text='Weiter', fg="green",
            command=self.setLabel)
        self.button.pack()
        self.root.minsize(150,100)
        self.root.mainloop()
    
    def setLabel(self):
        if self.blocked == False:
            self.label.config(text = self.entry.get())
            self.button.config(fg = "red")
            self.blocked = True
            self.block_label()
            
            
    def block_label(self):
        if self.blocked:
            if self.counter == 4:
                self.counter = 0
                self.blocked = False
                self.button.config(fg = "green")
            self.counter += 1
            self.label.after(1000, self.block_label)
        
a = Gui()
So ganz habe ich dich nicht verstanden, doch sucht du evt. sowas ?

gruss frank

Verfasst: Sonntag 5. Oktober 2008, 09:39
von Janux
Hallo Frank!
Ne sowas nicht. Es soll auf jeden Fall das Label mit dem Text blinken.
Wenn du nicht weisst was ich mein probier den Code einfach mal aus.
( Text eingeben - weiter - 4 sec warten - neuer Text - weiter )

P.S. Es soll ein Lernprogramm werden :)

Verfasst: Sonntag 5. Oktober 2008, 14:28
von numerix
Mir ist noch nicht klar, was GENAU das Programm leisten soll:

Der Text (Label) soll permanent blinken?
Bei Änderung der Eingabe soll unmittelbar nach dem Buttonclick die neue Eingabe blinken? Richtig?

Wie/was genau soll der Anwender mit dem Programm denn "lernen"?

Verfasst: Sonntag 5. Oktober 2008, 18:36
von kaytec
Hallo Janux !

Den Text blinken lassen ist nicht das Problem, doch ich versteh den Sinn von deinem Wunsch nicht.

gruss frank

Verfasst: Sonntag 5. Oktober 2008, 19:47
von kaytec
Hallo Janux !

Code: Alles auswählen

import Tkinter as tk

class Gui():
   
    def __init__(self):
        self.blocked = False
        self.text_show = True
        self.flash_time = 100
        self.label_text = ""
        self.root = tk.Tk()
        self.entry = tk.Entry(self.root)
        self.entry.pack()
        self.text = tk.StringVar()
        self.label = tk.Label(self.root)
        self.label.pack()
        self.button = tk.Button(self.root, text='Weiter', fg="green",
            command=self.setLabel)
        self.button.pack()
        self.root.minsize(150,100)
        self.flash_label()
        self.root.mainloop()
    
    def setLabel(self):
        if self.blocked == False:
            self.label_text = self.entry.get()
            self.button.config(fg = "red")
            self.blocked = True
            self.flash_time = 100
            
            
    def flash_label(self):
        if self.text_show:
            self.label.config(text = self.label_text)
            self.text_show = False
        else:
            self.label.config(text = "")
            self.text_show = True
        if self.flash_time == 1000:
            self.blocked = False
            self.button.config(fg = "green")
        self.flash_time += 100
        self.label.after(self.flash_time, self.flash_label)
        
a = Gui() 
Ob das Zuruecksetzen der Zeit Probleme machen koennte, kann ich dir nicht sagen.

gruss frank

Verfasst: Sonntag 5. Oktober 2008, 19:51
von Janux
Das Code-Snippet ist nur ein Teil aus meinem Lernprogramm.
Normalerweise ist kein Entry da und noch das passende Text-Gegenstück.
Der Text kommt aus einer Liste. Lernen möchte ich damit zum Beispiel Vokabeln.

Der Text soll permanet blinken. Die Pausen, wo kein Text zu sehen ist,
sollen mit der Zeit immer größer werden. Wenn ich auf 'weiter' klicke
soll das gleiche mit dem neuen Text beginnen.

Im Moment ist es so, dass dann die alte Funktion noch weiter läuft.
Deshalb gibt es dann eine Überlagerung zwischen der alten und der
neuen 'blink()' Funktion und der Text blinkt undefiniert.

Wegen der .after Funktion schaffe ich es nicht die Abbruchbedingung
in der Rekursion zu erfüllen, da ja gleich darauf die Funktion neu
gestartet werden muss. Deswegen habe ich eine 4 sec Pause eingebaut,
um das Problem darzustellen.

Mein Wunsch ist es, dass der neue Text ohne Überlagerung mit der alten
Blink-Funktion anfangen kann zu blinken.

Verfasst: Sonntag 5. Oktober 2008, 19:57
von Janux
kaytec hat geschrieben:
Ob das Zuruecksetzen der Zeit Probleme machen koennte, kann ich dir nicht sagen.

gruss frank
Ich glaube, dass ist genau was ich gemeint habe. Nur leider steig ich noch
nicht ganz durch und werde es mir morgen mal in Ruhe anschauen ....

Dank dir !!

Verfasst: Sonntag 5. Oktober 2008, 20:24
von kaytec
Hallo Janux !
Das mit den Vokabeln koenntest du mit itertools.cycle() machen.

gruss frank

Verfasst: Sonntag 5. Oktober 2008, 21:54
von yipyip
Hab' hier auch noch eine Lösung, mit der Du
vielleicht (hoffentlich :wink:) etwas anfangen kannst.

Code: Alles auswählen

#!/usr/bin/env python

####

import Tkinter as tk
import time as ti

####

class Gui():
   
   
    def __init__(self):

      self.root = tk.Tk()
      self.entry = tk.Entry(self.root)
      self.entry.pack()
      self.text = tk.StringVar()
      self.label = tk.Label(self.root, textvariable=self.text)
      self.label.pack()
      self.button = tk.Button(self.root, text='Weiter',
                              command=self.blink)
      self.button.pack()

      self.res_button = tk.Button(self.root, text='Reset',
                              command=self.reset)     
      self.res_button.pack()
      
      self.intervall = 400
      self.reset_iv = self.intervall
      self.state = 0

      self.root.mainloop()


    def blink(self):

      self.set_label()
      

    def set_label(self):

      if self.state:
        return
      
      self.text.set(self.entry.get())
      self.root.after(self.intervall, self.del_label)
      
      self.state ^= 1

      
    def del_label(self):

      if not self.state:
        return

      self.text.set(str(self.intervall))
      self.root.after(self.intervall, self.set_label)

      self.intervall += 100
      self.state ^= 1


    def reset(self):

      self.intervall = self.reset_iv

####

if __name__ == '__main__':

  Gui()
  
####
:wink:
yipyip

Verfasst: Sonntag 5. Oktober 2008, 23:27
von BlackJack
Nur mal so als Anmerkung: Der Hauptschleife den Auftrag zu geben irgend wann später die Funktion noch einmal auf zu rufen ist keine Rekursion.

Verfasst: Montag 6. Oktober 2008, 01:01
von kaytec
Hallo Janux !

Mit einer dict waere es auch gegangen, doch da bleiben immer noch Klammern im Text. Wird uns bestimmt BlackJack erklaeren.

Code: Alles auswählen

import Tkinter as tk

import itertools

class Gui():
    
    VOKABELN = [["dog", "Hund"], ["cat", "Katze"], ["mouse", "Maus"]]
    
    def __init__(self):
        self.text_show = True
        self.flash_time = 100
        self.vokabeln = itertools.cycle(self.VOKABELN)
        self.label_text = self.vokabeln.next()
        self.gui()
        
    def gui(self):
        self.root = tk.Tk()
        self.text = tk.StringVar()
        self.label = tk.Label(self.root)
        self.label.pack()
        self.button = tk.Button(self.root, text='Weiter', fg="green",
            command=self.setLabel)
        self.button.pack()
        self.root.minsize(150,100)
        self.flash_label()
        self.root.mainloop()
        
    
    def setLabel(self):
        self.label_text = self.vokabeln.next()
        self.flash_time = 100
            
            
    def flash_label(self):
        if self.text_show:
            self.label.config(text = self.label_text[0])
            self.text_show = False
        else:
            self.label.config(text = self.label_text[1])
            self.text_show = True
        self.flash_time += 100
        self.label.after(self.flash_time, self.flash_label)
        
a = Gui() 
gruss frank

Verfasst: Montag 6. Oktober 2008, 01:35
von DasIch
kaytec hat geschrieben:Mit einer dict waere es auch gegangen, doch da bleiben immer noch Klammern im Text. Wird uns bestimmt BlackJack erklaeren.
Hättest du mal ein kleines Beispiel um dass zu demonstrieren? Also bei mir klappts ohne Probleme:

Code: Alles auswählen

In [20]: from itertools import cycle

In [21]: vok = {"dog":"hund", "cat":"katze", "mouse":"maus"}

In [22]: f = cycle(vok.iteritems())

In [24]: f.next()
Out[24]: ('mouse', 'maus')

In [39]: english, german = f.next()

In [40]: english
Out[40]: 'dog'  

In [41]: german
Out[41]: 'hund'

Verfasst: Montag 6. Oktober 2008, 08:23
von kaytec
Hallo DasIch !

Ich wollte es ganz "schlau" machen und eine dict() dafuer quaelen.

Code: Alles auswählen

import itertools

VOKABELN = [{"dog" : "Hund"}, {"cat" : "Katze"}, {"mouse" : "Maus"}]

vokabeln = itertools.cycle(VOKABELN)
label_text = vokabeln.next()

print label_text.keys()
print label_text.values()

VOKABELN = [["dog", "Hund"], ["cat", "Katze"], ["mouse", "Maus"]] 

vokabeln = itertools.cycle(VOKABELN)
label_text = vokabeln.next()

print label_text[0]
print label_text[1]
gruss frank