funktion, die gleichzeitig mehrmals abläuft

Fragen zu Tkinter.
Antworten
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

ich versuche herauszufinden, wie man o.g. aufgabe löst. ich weiss, das hat nicht direkt was mit tkinter zu tun, aber ich wusste nicht genau wohin damit. am besten ein beispiel, was meinem problem am nächsten kommt:

ich habe ein canvas und in dem soll an der stelle an die ich mit der maus klicke ein text-widget erscheinen (kein problem). dieses soll dann aber von 10 auf 0 zählen (sekunden) und dann verschwinden (gelöscht werden). d.h. wenn ich viele clicks mache verschwinden die 'counter' alle in der click-reihenfolge wie damals die lemmings nach der atombome.

geht das? ist es ganz einfach und eine dumme frage? geht es nur unter einsatz von weiteren modulen (threading?-hab ich noch keine ahnung von)?

tausen dank für eure hilfe :) !
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

vielleicht hab ich mich misverständlich ausgedrückt, in o.g. beispiel soll natürlich pro click ein neuer und selbstständiger counter auftauchen.
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

alsoooo, noch ein versuch. bei meinem bisherigen code (s.u.) lassen sich zwar beliebig viele funktionen starten, die werden aber nacheinander abgearbeitet. das nehm ich python ja auch gar nicht übel, ich bräuchte nur einen (oder mehr) tipp(s), wo und wie ich nachsehe bzw. es anstelle, daß die counter (oder andere funktionen) gleichzeitig ablaufen, also jede mit ihrem eigenen start und davon abhängigen endpunkt.

i r g e n d j e m a n d eine idee?

ach, noch eine frage: warum funktioniert das time.sleep(0.1) nur, wenn ich innerhalb der funktion nochmal time importiere?




Code: Alles auswählen

from Tkinter import *
from time import *

################################

root = Tk()

root.minsize(width=320, height=380)
root.resizable(width=YES, height=YES)

frame03 = Frame(root, relief=FLAT, borderwidth=0,bg="#014589")
frame03.pack(fill=BOTH,expand=1)

rasen=Canvas(frame03,bg='green')
rasen.pack(fill=BOTH, expand=1)


def test(event):
    import time
    counter=rasen.create_text(event.x,event.y,text='')
    for i in range(10):
        rasen.itemconfigure(counter,text=str(9-i))
        rasen.update()
        time.sleep(0.1)
    rasen.delete(counter)

################################

root.bind('<Button-1>',test)

root.mainloop()
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

geogre hat geschrieben:i r g e n d j e m a n d eine idee?
Threads?
geogre hat geschrieben:ach, noch eine frage: warum funktioniert das time.sleep(0.1) nur, wenn ich innerhalb der funktion nochmal time importiere?
Das ist ein Beispiel dafuer, warum man from <module> import * nicht machen sollte. Im Modul time gibt es naemlich eine Funktion namens time. Die hast du mit dem Namen time importiert, also kannst du auf das Modul time nicht mehr mittels time.<funktion> zugreifen (denn time ist ja die importierte Funktion). Dafuer kannst du direkt sleep(...) statt time.sleep(...) benutzen.

Aber am besten schreibst du am Anfang deines Skriptes einfach nur import time.
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

'Threads?'

das ist bestimmt, davon bin ich überzeugt, sogar eine richtig gute idee ;) wenn es denn eine ist, hätte ich mir vielleicht eher 'Threads.' als 'Threads?' gewünscht, aber gut.

vielleicht hat ja jemand noch eine idee, wo ich einen leicht verständlichen einstieg dazu finden kann o.ä. ich habe in einigen code-beispielen mit zwei gegenläufigen zählern, die ich hier gefunden habe etwas versucht zu verstehen, aber so richtig angesprungen hat es mich bisher nicht.

danke wegen der time-geschichte! ich wusste nicht, daß es einen unterschied macht, wie man das modul importiert. danke :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

geogre hat geschrieben:das ist bestimmt, davon bin ich überzeugt, sogar eine richtig gute idee ;) wenn es denn eine ist, hätte ich mir vielleicht eher 'Threads.' als 'Threads?' gewünscht, aber gut.
In PyGTK gibt es die Idle-Funktion, die sowas ähnliches kann wie du willst.
geogre hat geschrieben:vielleicht hat ja jemand noch eine idee, wo ich einen leicht verständlichen einstieg dazu finden kann o.ä. ich habe in einigen code-beispielen mit zwei gegenläufigen zählern, die ich hier gefunden habe etwas versucht zu verstehen, aber so richtig angesprungen hat es mich bisher nicht.
Siehe UpdaterThread, das ist so ein Thread-Beispiel.
geogre hat geschrieben:danke wegen der time-geschichte! ich wusste nicht, daß es einen unterschied macht, wie man das modul importiert. danke :)
Ich habe noch [wiki]Modul_Import[/wiki] für dich.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

danke für die antwort!

das heisst wohl, es geht mit tkinter nicht? ich hatte bisher pygtk nicht und bin auch schon beim versuch es zu installieren gescheitert. die englische irre lange installationsanleitung dafür ist mir jetzt etwas zuviel und das setup.py hat mich nur gewarnt und sich dann mit einem kurz aufflackernden fehler verabschiedet. schade. ich dachte, es ginge vielleicht 'irgendwie einfach' :(

das pythonwiki mag ich, danke.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

geogre hat geschrieben:das heisst wohl, es geht mit tkinter nicht?
Doch, sicher. Das UpdaterThread-Beispiel funktioniert auch ohne PyGTK (der Thread-Teil, nicht der GUI-Teil).
geogre hat geschrieben:ich hatte bisher pygtk nicht und bin auch schon beim versuch es zu installieren gescheitert. die englische irre lange installationsanleitung dafür ist mir jetzt etwas zuviel und das setup.py hat mich nur gewarnt und sich dann mit einem kurz aufflackernden fehler verabschiedet. schade. ich dachte, es ginge vielleicht 'irgendwie einfach' :(
Hä? Also wenn ich PyGTK installiere, dann muss ich dazu zwei Installer aufrufen (inoffiziellen GTK-Installer für Windows & inoffiziellen PyGTK-Installer für Windows) und damit hat sich das. Was für ein Betriebssystem hast du, dann kann ich dir (warscheinlich) die notwendigen Schritte sagen.

Ich meine, wenn du Tkinter magst, dann bleib dabei, aber wenn du lieber ein modernes Toolkit hättest, dann ist PyGTK gar keine schlechte Wahl.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

ha! ich hab's auch geschafft. ich hatte mich (vielleicht wiedermal) etwas zu voreilig doof angestellt. aber es ist ja wenn man etwas bereits gelernt hat echt auch nicht so einfach zu verstehen wie schwer und anstrengend es ist/sein kann etwas herauszufinden von dem man z.t. gar nicht weiss was es ist bzw. ob es existiert. ich bin kein informatiker sondern quasi hobby und bedarfs-autodidakt und hab sehr viel freude und auch schon ein paar erfolgserlebnisse mit python.. und ich bin so dankbar für tipps etc. aus diesem forum!!! also danke an alle, die hier mir und anderen helfen!
jedenfalls hatte ich von

http://ftp.gnome.org/pub/GNOME/sources/pygtk/2.8/

eine dateisammlung (?) runtergeladen die eine sehr aufwändige wie gesagt englische installationsanleitung (erst noch c-compiler installieren, dann compilieren etc.) mitbrachte und das hat mich abgeschreckt. ich hab aber dank eines anderen thread hier (wie installiere ich pygtk unter windows oder so ähnlich) diese zwei dateien gefunden und schwupps war's fertig installiert und der bsp. code lief.

gtk-win32-devel-2.8.14-rc1.exe
pygtk-2.8.2-1.win32-py2.4.exe

ich bin allerdings noch nicht so ganz schlau draus geworden, ich weiss eigentlich gar nicht so genau was der code macht (läuft ein counter weiter und wenn man den button klickt wird zeitverzögert die aktuelle laufzeit darauf angezeigt?) und vor allem nicht wie ich das nach tkinter übersetzen könnte. bei tkinter möchte ich erstmal bleiben, klar ist mir auch einiges zu unmodern, aber ich bin da bescheiden und möchte erstmal so ein paar sachen lernen bevor ich meine optischen ansprüche auslebe.

z.zt. versuche ich mich an einer art kleinem brettspiel das sich in einem canvas abspielt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

geogre hat geschrieben:ich bin kein informatiker sondern quasi hobby und bedarfs-autodidakt und hab sehr viel freude und auch schon ein paar erfolgserlebnisse mit python.. und ich bin so dankbar für tipps etc. aus diesem forum!!!
Ich bin auch Autodidakt ;)
geogre hat geschrieben:eine dateisammlung (?) runtergeladen die eine sehr aufwändige wie gesagt englische installationsanleitung (erst noch c-compiler installieren, dann compilieren etc.) mitbrachte und das hat mich abgeschreckt.
Ab GTK 2.8 gibt es sogar offizielle GTK Pakete. Allerdings ist der Installer bequemer, zweifellos. Zudem hat er auch noch Glade.
geogre hat geschrieben:gtk-win32-devel-2.8.14-rc1.exe
pygtk-2.8.2-1.win32-py2.4.exe
Der Gladewin32 Installer :) Ich würde allerdings gleich PyGTK 2.8.5 nehmen, weil es einfach schon da ist :D
geogre hat geschrieben:ich bin allerdings noch nicht so ganz schlau draus geworden, ich weiss eigentlich gar nicht so genau was der code macht (läuft ein counter weiter und wenn man den button klickt wird zeitverzögert die aktuelle laufzeit darauf angezeigt?) und vor allem nicht wie ich das nach tkinter übersetzen könnte. bei tkinter möchte ich erstmal bleiben, klar ist mir auch einiges zu unmodern, aber ich bin da bescheiden und möchte erstmal so ein paar sachen lernen bevor ich meine optischen ansprüche auslebe.
Wer so nett bittet, für den mache ich auch gerne ein anderes Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-
import threading, time 

class CounterThread(threading.Thread):
    threads = 0
    def __init__(self, delay, maxcount):
        self.number = CounterThread.threads
        CounterThread.threads += 1
        self.delay = delay
        self.maxcount = maxcount
        threading.Thread.__init__(self)
   
    def run(self):
        count = 0
        print 'Entering thread #%d' % self.number
        while count < self.maxcount:
            print 'Running thread #%d' % self.number
            count += 1
            time.sleep(self.delay)
        print 'Exiting thread #%d' % self.number

def main():
    ct1 = CounterThread(1, 5)
    ct1.start()
    ct2 = CounterThread(1, 7)
    ct2.start()

if __name__ == '__main__':
    main()
Hier hast du einen Thread, der alle delay-Sekunden aufgerufen wird, irgendwas mache und sich schlafen legt und das maxcount Male. HTH!
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

wow! tausend dank!!! das gibt mir gleich auch noch einen schubs zum oop lernen, darum hatte ich mich bisher erfolgreich gedrückt ;) wobei ich da diese kombination aus def main(), if name=main: main() irgendwie nicht so ganz verstehe (klingt irgendwie doppelt gemoppelt) aber das ist ja auch ein ganz anderes thema und das find ich bestimmt auch in einem meiner beiden py-bücher, deren oop-kapitel ich wie gesagt bisher ausgelassen habe...

aber: so sehr mich das skript auch anleuchtet und mir irgendwie einleuchtet (die thread-geschichte) ... es läuft bei mir irgendwie nicht :( wahrscheinlich mein fehler, aber ich hab bisher erfolglos experimentiert. es zeigt jeweils das 'entering' und 'running' an und bleibt dann jedoch hängen und muss gekillt werden. ich benutze py 2.4.2 auf w2kp...

auf jeden fall DAAAANKE !!! das gibt viele neue synapsen :)
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

oh mann... gerade jetzt hab ich's doch zum laufen gekriegt, ich hatte es wie ich das sonst immer tue mit idle ge-edited und wenn ich es dort mit f5 starte schmiert es irgendwie ab (bestimmt ein typischer anfängerdenkfehler)

wenn ich es direkt ausführen lasse, geht's natürlich. danke :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

geogre hat geschrieben:wow! tausend dank!!! das gibt mir gleich auch noch einen schubs zum oop lernen, darum hatte ich mich bisher erfolgreich gedrückt ;)
Na, man kann auch statt dem Modul threading, welches sehr praktisch ist auch die Low-Level Variante thread nehmen, nur finde ich threading einfach sauberer.
geogre hat geschrieben:wobei ich da diese kombination aus def main(), if name=main: main() irgendwie nicht so ganz verstehe (klingt irgendwie doppelt gemoppelt) aber das ist ja auch ein ganz anderes thema und das find ich bestimmt auch in einem meiner beiden py-bücher, deren oop-kapitel ich wie gesagt bisher ausgelassen habe...
Das hat mit OOP nichts zu tun, sondern mit der weise, wie Python Module importiert. Ich nenne das Ding einen Import-Hook, den habe ich schon öfter erklärt (wenns immer noch unklar ist, nachfragen, dann mach ichs vielleicht als Seite im Wiki).
geogre hat geschrieben:oh mann... gerade jetzt hab ich's doch zum laufen gekriegt, ich hatte es wie ich das sonst immer tue mit idle ge-edited und wenn ich es dort mit f5 starte schmiert es irgendwie ab (bestimmt ein typischer anfängerdenkfehler)

wenn ich es direkt ausführen lasse, geht's natürlich. danke :)
Deswegen auch hier das Motto: [wiki]IDLE_ist_evil[/wiki] ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
N317V
User
Beiträge: 504
Registriert: Freitag 8. April 2005, 13:23
Wohnort: München

Leonidas hat geschrieben:Das hat mit OOP nichts zu tun, sondern mit der weise, wie Python Module importiert. Ich nenne das Ding einen Import-Hook, den habe ich schon öfter erklärt (wenns immer noch unklar ist, nachfragen, dann mach ichs vielleicht als Seite im Wiki).
Was mir irgendwie umständlich vorkommt, ist, dass Du dafür extra eine main() definierst. Ich mach diese Aufrufe einfach gleich in den if-Block. Das ins Wiki zu schreiben find ich sowieso gut.
Es gibt für alles eine rationale Erklärung.
Außerdem gibt es eine irrationale.

Wie man Fragen richtig stellt
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

N317V hat geschrieben:Was mir irgendwie umständlich vorkommt, ist, dass Du dafür extra eine main() definierst.
Hi N317V!

Einer der Vorteile der eigenen main() ist der, dass dir der Namensraum beim Importieren deines Moduls nicht vollgemüllt wird.

Der nächste Vorteil ist, du kannst in die main() Code schreiben, der gezielt ausgeführt werden kann. Beim Importieren deines Moduls wird nichts ausgeführt. Du kannst die main() dann explizit aufrufen. Würdest du alles unterhalb der if-Anweisung schreiben, könntest du diesen Code niemals von einem anderen Modul aus aufrufen. Und man weiß doch nicht immer schon im Voraus, ob man das nicht doch einmal brauchen könnte... :mrgreen:

lg
Gerold
:-)
Zuletzt geändert von gerold am Dienstag 11. April 2006, 07:55, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
N317V
User
Beiträge: 504
Registriert: Freitag 8. April 2005, 13:23
Wohnort: München

Greetings gerold,
gerold hat geschrieben: Einer der Vorteile der eigenen main() ist der, dass dir der Namensraum beim Importieren deines Moduls nicht vollgemüllt wird.
Das verstehe ich nicht so ganz. Der if-Block wird gar nicht ausgeführt, oder? Wie kann der was vollmüllen?
Es gibt für alles eine rationale Erklärung.
Außerdem gibt es eine irrationale.

Wie man Fragen richtig stellt
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

N317V hat geschrieben:
gerold hat geschrieben: Einer der Vorteile der eigenen main() ist der, dass dir der Namensraum beim Importieren deines Moduls nicht vollgemüllt wird.
Das verstehe ich nicht so ganz. Der if-Block wird gar nicht ausgeführt, oder? Wie kann der was vollmüllen?
Hi N317V!

Du hast Recht. Ich habe mich von meiner IDE beeinflussen lassen. Es wird nicht der Python-Namensraum sondern die Codevervollständigung meiner IDE zugemüllt. WingIDE bietet die Variablen in "b.py" zur Auswahl an. Es wird aber wie erwartet ein Fehler ausgeworfen, wenn das Skript ausgeführt wird.

a.py:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

if __name__ == "__main__":
    var_a = "Hallo"
    var_b = "Welt"
b.py:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import a

a.var_a
a.var_b
lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

hallo,
euch allen nochmal vielen dank für antworten, tipps und hilfen... ich hab nochmal ein bisschen experimentiert und für mein ursprüngliches beispiel (eine fläche mit eigenständigen zählern wo man hinklickt) eine wie ich finde total einfache methode mit 'thread' gefunden, wollte die nur hier kurz mitteilen (kommentare natürlich willkommen). mein problem ist jedenfalls erstmal mehr als gelöst - danke !!!

Code: Alles auswählen

from Tkinter import *
import time, thread

root = Tk()
root.minsize(width=320, height=380)
root.resizable(width=YES, height=YES)

frame03 = Frame(root, relief=FLAT, borderwidth=0)
frame03.pack(fill=BOTH,expand=1)
rasen=Canvas(frame03,bg='green')
rasen.pack(fill=BOTH, expand=1)

def meinthread(event):
    koordinaten=[event.x,event.y]
    thread.start_new_thread(test,(koordinaten[0],koordinaten[1]))

def test(x,y):
    counter=rasen.create_text(x,y,text='')
    for i in range(10):
        rasen.itemconfigure(counter,text=str(9-i))
        rasen.update()
        time.sleep(1)
    rasen.delete(counter)

root.bind('<Button-1>',meinthread)
root.mainloop()
Antworten