Schleife mit urwid

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

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
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.
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

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.
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.
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

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
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()
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

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
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.
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

Ok, verstehe.

Macht Sinn ja.

Vielen Dank und noch ein frohes Osterfest.
Antworten