Seite 1 von 1

Schleife mit urwid

Verfasst: Samstag 19. April 2014, 14:40
von Avantasia1975
Moin und frohe Ostern.

Ich habe da mal ne Frage zu urwid.
Ich möchte letztlich im footer nen Countdown haben und wenn dieser abgelaufen ist, den Body erneuern.

Ich hing nun erstmal 3 Tage fest da ich nicht in der Lage war ne Schleife zu finden die geht. Die Doku ist ja eher dürftig.

Nun habe ich die Schleife hin bekommen und wollte hier nur mal wissen, ob das der richtige Weg ist.
Ich kann mir das so nicht vorstellen auch wenn es geht.

Code: Alles auswählen

import urwid as u
import time

def CountDown(loop, data):
    for i in range(59 , 0, -1):
        loop.widget.body.set_text(str(i))
        loop.draw_screen()
        time.sleep(1)

text = u.Text("60", align = "center")
text = u.Filler(text)
loop = u.MainLoop(text)
loop.set_alarm_in(1, CountDown)
loop.run()
Vielen Dank und ein schönes Wochenende

Re: Schleife mit urwid

Verfasst: Samstag 19. April 2014, 14:57
von BlackJack
@Avantasia1975: Du findest da keine Schleifen für weil man solche Schleifen bei GUI-Toolkits nicht verwenden kann — solange Deine Schleife läuft, läuft die Hauptschleife des GUI-Toolkits nicht mehr.

Man würde so etwas wie `set_alarm_in()` nutzen und zwar um einmal in der Sekunde den Countdown aktualisieren zu lassen.

Re: Schleife mit urwid

Verfasst: Samstag 19. April 2014, 15:02
von Avantasia1975
Vielen Dank für die Antwort.

Habe das auch grad gemerkt denn das unhandled_input geht nicht :) .

Das "set_alarm_in" habe ich ja genutzt aber es wird ja nur einmal aufgerufen.
Ich bräuchte ja wieder ne Schleife um die Funktion aufzurufen.

Hmm, oder ich baue das noch mit in die Funktion ein ?!

Vielen Dank nochmal.
Werde mal weiter probieren.

Die Doku ist ja nicht so der Bringer :(


So nun geht es so:

Code: Alles auswählen

import urwid as u
import time

countdown = 59
def CountDown(loop, data):
    global countdown
    loop.widget.body.set_text(str(countdown))
    loop.draw_screen()
    countdown -= 1
    if countdown > 0:
        loop.set_alarm_in(1, CountDown)

def ExitOnQ(input):
    if input in ("q", "Q"):
        raise u.ExitMainLoop()

text = u.Text("60", align = "center")
text = u.Filler(text)
loop = u.MainLoop(text, unhandled_input = ExitOnQ)
loop.set_alarm_in(1, CountDown)
loop.run()
Ich fände es besser wenn man der "run" Methode eine Funktion mit geben könnte.

Aber gut, man kann nicht alles haben.

Re: Schleife mit urwid

Verfasst: Samstag 19. April 2014, 15:35
von BlackJack
@Avantasia1975: Das ``global`` ist äusserst unschön. Man kann die Zeit doch als `data` weiterreichen. Und man sollte es auch so schreiben können, dass `set_alarm_in()` nur in der Countdown-Funktion aufgeruefen werden muss.

`ExitOnQ()` enspricht nicht den Namenskonventionen: Style Guide for Python Code.

Re: Schleife mit urwid

Verfasst: Samstag 19. April 2014, 16:03
von Avantasia1975
Ich wüsste im Moment leider nicht wie ich dann in die CountDown-Funktion kommen soll wenn ich "set_alarm_in()" nur in dieser Funktion hätte?

Ich schreibe die Programme nur für mich bzw. meine Kollegen. Da spielen die Namen nicht so ne Rolle.
Obwohl es sicher besser wäre, wenn ich mich danach richte. Ich schaue mir das mal an.
Danke

Re: Schleife mit urwid

Verfasst: Samstag 19. April 2014, 16:19
von BlackJack
@Avantasia1975: In dem Du die Funktion einfach aufrufst.

Das `draw_screen()` ist nicht mehr nötig wenn die GUI-Hauptschleife die Kontrolle hat.

Code: Alles auswählen

from urwid import CENTER, ExitMainLoop, Filler, MainLoop, Text
 

def count_down(loop, (text, count)):
    text.set_text(str(count))
    if count > 0:
        loop.set_alarm_in(1, count_down, (text, count - 1))
 

def exit_on_q(input_):
    if input_.lower() == 'q':
        raise ExitMainLoop()
 

def main():
    text = Text('', align=CENTER)
    loop = MainLoop(Filler(text), unhandled_input=exit_on_q)
    count_down(loop, (text, 60))
    loop.run()


if __name__ == '__main__':
    main()

Re: Schleife mit urwid

Verfasst: Samstag 19. April 2014, 16:40
von Avantasia1975
Oh super, vielen Dank für den Code.

Aber irgendwo scheint mir etwas in Python zu fehlen.
In Zeile 18 rufst du ja die Funktion "count_down" auf.
So wie ich das bisher verstanden habe, würde diese Funktion nun ausgeführt werden und als "Schleife" laufen da die Funktion sich ja selbst aufruft.
"loop.run()" würde erst nachdem "count_down" fertig ist aufgerufen. :K

Na da hab ich erstmal etwas zum grübeln.

Nochmals, vielen Dank

Re: Schleife mit urwid

Verfasst: Samstag 19. April 2014, 17:37
von BlackJack
@Avantasia1975: Die Funktion kehrt so ziemlich sofort wieder zurück, denn sie ruft sich *nicht* selbst auf. Die ruft `loop.set_alarm_in()` auf, das ruft die Funktion aber auch nicht auf, sondern vermerkt nur das sie in einer Sekunden aufgerufen werden soll, und kehrt sofort wieder zurück. Dass das tatsächlich passiert ist Aufgabe von der `urwid`-Hauptschleife die in `run()` läuft.

Re: Schleife mit urwid

Verfasst: Samstag 19. April 2014, 17:48
von Avantasia1975
Ok, verstehe.

Macht Sinn ja.

Vielen Dank und noch ein frohes Osterfest.