Rekursion abbrechen ++

Fragen zu Tkinter.
Antworten
Janux
User
Beiträge: 78
Registriert: Donnerstag 12. Juni 2008, 21:11

Samstag 4. Oktober 2008, 22:20

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. :?
mfg ... Janux
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Sonntag 5. Oktober 2008, 08:39

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
Janux
User
Beiträge: 78
Registriert: Donnerstag 12. Juni 2008, 21:11

Sonntag 5. Oktober 2008, 09:39

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 :)
mfg ... Janux
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Sonntag 5. Oktober 2008, 14:28

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"?
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Sonntag 5. Oktober 2008, 18:36

Hallo Janux !

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

gruss frank
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Sonntag 5. Oktober 2008, 19:47

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
Janux
User
Beiträge: 78
Registriert: Donnerstag 12. Juni 2008, 21:11

Sonntag 5. Oktober 2008, 19:51

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.
mfg ... Janux
Janux
User
Beiträge: 78
Registriert: Donnerstag 12. Juni 2008, 21:11

Sonntag 5. Oktober 2008, 19:57

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 !!
mfg ... Janux
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Sonntag 5. Oktober 2008, 20:24

Hallo Janux !
Das mit den Vokabeln koenntest du mit itertools.cycle() machen.

gruss frank
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Sonntag 5. Oktober 2008, 21:54

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
BlackJack

Sonntag 5. Oktober 2008, 23:27

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.
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Montag 6. Oktober 2008, 01:01

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
DasIch
User
Beiträge: 2452
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Montag 6. Oktober 2008, 01:35

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'
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Montag 6. Oktober 2008, 08:23

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
Antworten