gtk.ProgressBar

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
bmh1980
gelöscht
Beiträge: 60
Registriert: Montag 26. Januar 2004, 17:13
Kontaktdaten:

Hallo.

Versuche gerade einen ProgressBar mit PyGTK zur Bewegung zu bringen.

Dazu habe ich in der PyGTK FAQ auch einen Artikel gefunden. Aber so ganz verstehe ich den nicht.

Code: Alles auswählen

while work_left:
    ...do something...
    progressbar.set_fraction(...)
    while gtk.events_pending():
        gtk.main_iteration()

Soweit so klar. Nur wofür steht hier work_left und was müsste bei progressbar.set_fraction(...) stehen, wenn die Anzeigen während der Arbeit von links nach rechts und wieder zurück soll?

Aufrufen müsste ich den ProgressBar wohl mit pulse(). Und set_fraction() müsste wohl durch set_pulse_setp() ersetzt werden.

Da ich aber ziemlich auf dem Schlauch stehe, bin ich mir da nicht sicher. Und probieren geht net, da ich ja schon an der ersten Zeile mit work_left scheitere.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Zur Progressbar habe ich auch noch ein Beispiel:

Code: Alles auswählen

import gtk
import math

def fibonacci(pbar, max=10):
    f0, f1 = 0, 1
    for i in xrange(max):
        f0, f1 = f1, f0 + f1
        for j in xrange(100000):
            j = math.sqrt(21342)
        pbar.set_text('%d'%f0)
        pbar.set_fraction((i+1)/float(max))
        yield True
    yield False

def start_work(button, pbar, spin):
    generator = fibonacci(pbar, spin.get_value_as_int())
    gtk.idle_add(generator.next)
        
def main():
    win = gtk.Window()
    win.set_border_width(12)
    win.connect('destroy', gtk.main_quit)
    vbox = gtk.VBox()
    vbox.set_spacing(12)

    pbar = gtk.ProgressBar()
    vbox.pack_start(pbar)

    hbox = gtk.HBox()
    hbox.set_spacing(6)
    spin = gtk.SpinButton(gtk.Adjustment(10, 3, 100, 1, 1))
    hbox.pack_start(spin)
    
    button = gtk.Button(stock=gtk.STOCK_EXECUTE)
    button.connect('clicked', start_work, pbar, spin)
    hbox.pack_start(button)

    vbox.pack_start(hbox)
    
    win.add(vbox)
    win.show_all()
    
    gtk.main()

if __name__ == '__main__':
    main()
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
hehejo
User
Beiträge: 56
Registriert: Freitag 18. Februar 2005, 18:24
Wohnort: Stein
Kontaktdaten:

Leonidas hat geschrieben:

Code: Alles auswählen

import gtk
import math

def fibonacci(pbar, max=10):
    f0, f1 = 0, 1
    for i in xrange(max):    # Warum nicht range(max)?
        f0, f1 = f1, f0 + f1
        for j in xrange(100000):
            j = math.sqrt(21342)
        pbar.set_text('%d'%f0)
        pbar.set_fraction((i+1)/float(max))
        yield True    
    yield False       

def start_work(button, pbar, spin):
    generator = fibonacci(pbar, spin.get_value_as_int())
    gtk.idle_add(generator.next) 
Danke für das Beispiel: Da kann ich bestimmt schon wieder was lernen.

Was ist der Unterschied zwischen range und xrange?

Danke
Zuletzt geändert von hehejo am Montag 7. März 2005, 11:58, insgesamt 1-mal geändert.
Gruß, Johannes
[b][color=red]ascii stupid question,
get stupid ansii[/color][/b]
[url]http://www.hehejo.de[/url]
bmh1980
gelöscht
Beiträge: 60
Registriert: Montag 26. Januar 2004, 17:13
Kontaktdaten:

Leonidas hat geschrieben:Zur Progressbar habe ich auch noch ein Beispiel:
Danke für das Beispiel Leonidas. Leider bin ich damit aber kein Stück weiter. :?

Vielleicht bin ich gerade nur zu blöd, aber ich verstehs immer noch nicht.

Ich brauche/hätte gerne einen ProgressBar, der sich solange von links nach rechts und wieder zurück bewegt, wie, zum Beispiel nach einer Datei gesucht wird.

Und wie gesagt. Entweder bin ich zu blöd, oder dein Beispiel bringt mich bei der Aufgabe wirklich nicht weiter.

Könntest du mir das vielleicht mal für gaaanz blöde erklären? :wink:
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

hehejo hat geschrieben:Was ist der Unterschied zwischen range und xrange?
range erstellt eine Liste, die so lang ist wie du halt angibst und xrange erstellt einen iterator. Das ist ein generator, der üblicherweise etwas schneller ist und weiteaus weniger speicher braucht, da er so zu sagen on-the-fly die elemente erstellt und nicht erst eine Liste durch die for durchgeht.

@bmh1980: Ich erstellt dir so einen Code, ok? Musst aber etwas warten bis ich wieder daheim bin.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
hehejo
User
Beiträge: 56
Registriert: Freitag 18. Februar 2005, 18:24
Wohnort: Stein
Kontaktdaten:

Danke, für die Erklärung.
Wollte eben gerade schreiben dass ich durch intensive Forensuche das auch rausbekommen habe - aber nochmal danke!
Gruß, Johannes
[b][color=red]ascii stupid question,
get stupid ansii[/color][/b]
[url]http://www.hehejo.de[/url]
bmh1980
gelöscht
Beiträge: 60
Registriert: Montag 26. Januar 2004, 17:13
Kontaktdaten:

Leonidas hat geschrieben:@bmh1980: Ich erstellt dir so einen Code, ok? Musst aber etwas warten bis ich wieder daheim bin.
Hab ich denn ne Wahl? :wink:

Nee. Kein Problem. Bin ja froh, wenn mir geholfen wird.

Das mit dem (verflixten) ProgressBar kann ich erstmal zurückstellen. Das Fenster in das der soll, ist zwar weitestgehend fertig, hab aber noch einige andere Fenster und Funktionen vor mir.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Okay, treue wird belohnt ;)

Dieser Code ist nur als Beispielcode zu nehmen, da er nicht besonders sauber ist, aber wenn du Fragen hast nur zu.

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-
import gtk
import math

val = 0
raising = True

def start_work(button, pbar):
    global val, raising
    if val == 10:
        raising = False
    if val == 0:
        raising = True
        
    if raising:
        val += 1
    else:
        val -= 1
    
    pbar.set_text('%d%%' % val)
    pbar.set_fraction(val/10.0)
        
def main():
    win = gtk.Window()
    win.set_border_width(12)
    win.connect('destroy', gtk.main_quit)
    vbox = gtk.VBox()
    vbox.set_spacing(12)

    pbar = gtk.ProgressBar()
    pbar.set_text('0%')
    vbox.pack_start(pbar)
    
    hbox = gtk.HBox()
    button = gtk.Button(stock=gtk.STOCK_EXECUTE)
    button.connect('clicked', start_work, pbar)
    hbox.pack_start(button)

    vbox.pack_start(hbox)
    
    win.add(vbox)
    win.show_all()
    
    gtk.main()

if __name__ == '__main__':
    main()
Du musst halt auf den Button klicken, dann geht die Fortschrittsanzeige 10% vor, oder nach 100% um 10% zurück. set_fraction setzt den gefüllten Anteil der Fortschrittsleiste.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
bmh1980
gelöscht
Beiträge: 60
Registriert: Montag 26. Januar 2004, 17:13
Kontaktdaten:

Okay. Soweit klar. Aber ich brauche etwas in der Form:

Code: Alles auswählen

def find_files():
    for item in os.popen('find /usr -type l').readlines():
        print item.rstrip().lstrip()

while find_files():
    frac = frac + 0.01
    if frac == 1.0:
        frac = 0.0
    pbar.set_fraction(frac)
Jedenfalls waren das meine Testversuche, die natürlich nicht geklappt haben.

Selbst mit diesem (mir immer noch nicht ganz verständlichem) gtk.events_pending()/gtk.main_iteration() klappt es nicht.

Ich vermute mal, dass da irgendwo ein return True/False oder yield True/False hingehört.

Aber ich komm nicht weiter. Selbst Google bringt nur absoluten Müll.

Ist ein ProgressBar so etwas Seltsamen, dass es nicht mal im Netz Beispiele dafür gibt?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

bmh1980 hat geschrieben:Ist ein ProgressBar so etwas Seltsamen, dass es nicht mal im Netz Beispiele dafür gibt?
Nicht doch, es gibt doch Doku.

Und jetzt noch etwas zu deinem Problem:

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-
import gtk

val = 0
raising = True

foundfiles = range(75)

def start_work(button, pbar):
    frac = 0.0
    for item in foundfiles:
        frac = frac + 0.01
        if frac > 1.0:
            frac = 0.0
        pbar.set_fraction(frac)
        
def main():
    win = gtk.Window()
    win.set_border_width(12)
    win.connect('destroy', gtk.main_quit)
    vbox = gtk.VBox()
    vbox.set_spacing(12)

    pbar = gtk.ProgressBar()
    vbox.pack_start(pbar)
    
    hbox = gtk.HBox()
    button = gtk.Button(stock=gtk.STOCK_EXECUTE)
    button.connect('clicked', start_work, pbar)
    hbox.pack_start(button)

    vbox.pack_start(hbox)
    
    win.add(vbox)
    win.show_all()
    
    gtk.main()

if __name__ == '__main__':
    main()
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
bmh1980
gelöscht
Beiträge: 60
Registriert: Montag 26. Januar 2004, 17:13
Kontaktdaten:

Nochmals danke für die Mühe. Aber so ganz verstehe ich das immer noch nicht. :cry: Sorry!

So weit ich das sehe und verstehe, wird der ProgressBar ja nur während der Arbeit mit foundfiles bewegt.

Nur ich hätte halt noch gerne, dass er schon beweget wird, während foundfiles erstellt wird.

Da gerade das viel Zeit in Anspruch nimmt. Das soll verhindern, dass der Benutzer denkt, dass das Skript hängt oder mit der Arbeit fertig ist, bzw. gar nicht arbeitet, obwohl dem halt nicht so ist.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Wie wärs damit:

Code: Alles auswählen

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

raising = True

def foundfiles():
    for i in xrange(100):
        time.sleep(0.1)
        yield i
    
def _work(button, pbar):
    gtk.idle_add(g.next)

def start_work(button, pbar):
    frac = 0.0
    for item in foundfiles():
        frac = frac + 0.01
        if frac > 1.0:
            frac = 0.0
        pbar.set_fraction(frac)
        yield True
       
def main():
    win = gtk.Window()
    win.set_border_width(12)
    win.connect('destroy', gtk.main_quit)
    vbox = gtk.VBox()
    vbox.set_spacing(12)

    pbar = gtk.ProgressBar()
    vbox.pack_start(pbar)
   
    hbox = gtk.HBox()
    button = gtk.Button(stock=gtk.STOCK_EXECUTE)
    button.connect('clicked', _work, pbar)
    hbox.pack_start(button)

    vbox.pack_start(hbox)
   
    win.add(vbox)
    win.show_all()
    
    global g
    g = start_work(button, pbar)
   
    gtk.main()

if __name__ == '__main__':
    main()
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
bmh1980
gelöscht
Beiträge: 60
Registriert: Montag 26. Januar 2004, 17:13
Kontaktdaten:

Super, danke! Funktioniert so, wie es soll.

Ich nehme mal an, dass hier die Hauptlösung idle_add ist, oder?

Was ist denn aber bitte yield? Python bringt mit bei help(yield) immer nur einen Error. Und in meinen Büchern find ich auch nichts dazu.

[EDIT]
Sobald das Skript mit der Arbeit fertig ist, bekomme ich die Meldung "StopIteration".

Was ist das? Kann man das irgendwie innerhalb des Skriptes abstellen?
[/EDIT]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

bmh1980 hat geschrieben:Ich nehme mal an, dass hier die Hauptlösung idle_add ist, oder?
Ja, kombiniert mit den Generatoren, siehe unten.
bmh1980 hat geschrieben:Was ist denn aber bitte yield? Python bringt mit bei help(yield) immer nur einen Error. Und in meinen Büchern find ich auch nichts dazu.
yield ist ein Schlüsselwort, kein Befehl, daher hat help() dazu ebensowenig wie zu "and", "return" usw. yield ist des Gegenstück zu return in einem Generator, die es erst seit Python 2.2 gibt. Es gibt einen Wert zurück, und "friert" die Funktion ein, so dass sie beim nächsten Aufruf von der gleichen Stelle fortgesetzt wird.
bmh1980 hat geschrieben:[EDIT]
Sobald das Skript mit der Arbeit fertig ist, bekomme ich die Meldung "StopIteration".

Was ist das? Kann man das irgendwie innerhalb des Skriptes abstellen?
[/EDIT]
StopIteration ist eine Exception die Auftritt, wenn der Generator vollständig durchläuft. Aber sie sollte nicht auftreten und dass dort was angezeigt wird liegt, wie ich denke daran, dass GTK irgendwie in die Ausnahmenverwaltung reinpfuscht. Wenn du willst kann ich mal in der PyGTK Mailingliste nachfragen, wie man das wegbekommt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten