Hallo zusammen,
ich habe da ein Problem wo ich jetzt schon seit 4 Stunden einfach nicht so richtig eine Lösung zu finde. Es ist auch nicht einfach zu erklären ich hoffe aber es gelingt mir so das ihr es verstehen könnt.
Also ich habe auf einer Oberfläche einen Button und eine Progressbar. Soweit so gut (natürlich sind noch mehr dinge vorhanden aber es geht um das zusammenspiel der beiden). Sobald der Button gedrückt wird startet eine Suchanfrage im Internet. Nun habe ich mir überlegt das es ja ganz nett wäre wenn man eine kleine Progressbar einbaut die Pulsed solange die Suchanfrage dauert.
So und nun kommts....... Das Problem ist das wenn ich den Button drücke bleibt dieser gedrückt weil ja die Suchanfrage noch arbeitet und das Pulsen startet auch erst danach wenn der Button wieder loslässt aber dann ist ja der eigentliche Gag vorbei. Dann soll die Bar ja gar nicht mehr Pulsen.
Hier mal ein bisschen Beispiel Code ist aber wirklich nur Pseudo damit ihr ein bisschen ein Bild davon bekommt.
def on_click_search:
pulsen
suchanfrage
pulsen ende
Ich habe schon verschiedenste varianten probiert die PyGtk her gibt. Die da wären.
gobject.timeout(), gobject.idle_add; gtk.gdk.threads_enter() u. leave()
und Python os.fork() <- führt aber in schwere Fehler
Also wie gesagt ich will das das Pulsen nur solange läuft wie die Suchanfrage dauert.
Kann mir vielleicht jemand dabei helfen ..... sonst lass ich den Effekt einfach weg wenn das nicht möglich ist.
PyGTK: Button Klick verhalten und Prozesse
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Mit ``gobject.idle_add`` eine die Suche starten und die Progressbar auf pulsierend stellen. Wenn die Funktion die die Suche ausführt fertig ist, von dieser die Progressbar zurückstellen lassen.
Edit: Thread verschoben.
Edit: Thread verschoben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- veers
- User
- Beiträge: 1219
- Registriert: Mittwoch 28. Februar 2007, 20:01
- Wohnort: Zürich (CH)
- Kontaktdaten:
Ich habe in meinen gtk helpern die folgende Funktion:
Versuch mal diese Funktion aufzurufen nach dem du die Progressbar auf pulsierend gesetzt hast. Könnte funktionieren.
Code: Alles auswählen
def gtk_yield():
"""process all the peding events in the mainloop"""
while gtk.events_pending():
gtk.main_iteration()
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
erst mal danke euch beiden für eure Antworten. Puhh ich bin froh das jemand das verstehen konnte was ich meine....
Ok also ich versuche gerade mit deiner Funktion zu arbeiten veers. Aber leider funktioniert diese auch so das erst wenn die suche zu ende ist und der Button los lässt geht das Pulsieren los.
Hier mal der Code ausschnitt:
Ok also ich versuche gerade mit deiner Funktion zu arbeiten veers. Aber leider funktioniert diese auch so das erst wenn die suche zu ende ist und der Button los lässt geht das Pulsieren los.
Hier mal der Code ausschnitt:
Code: Alles auswählen
def on_search(self, data):
gobject.timeout_add(100,self.bar_searching)
self.gtk_yield()
text = self.search_entry.get_text()
self.aur.clear_information()
self.aur.search(text)
if self.aur.is_package():
self.on_information()
else:
self.no_pack_dialog()
Die `bar_searching`-Methode könnte eventuell noch solch einen `gtk_yield`-Aufruf vertragen. Prinzipiell eben überall dort, wo du die GUI veränderst und "blockierst", also nicht sofort zur gtk-Hauptschleife zurückspringst.
Das da oben ist der Code den der Button ausführt und die Bar hat diesen Code nichts dolles soll halt nur ein bisschen Pulsen.
Code: Alles auswählen
def bar_searching(self):
self.gtk_yield()
self.progressbar.set_text('Searching...')
self.progressbar.pulse()
return True
Ja auch wenn ich es so schreibe wie du es sagst geht es leider nicht. Ich bastel schon die ganze Zeit mir nen Wolf wie ich das hinbekomme das es vorher läuft. Aber leider komme ich keinen Schritt weiter. Das einzige was geklappt hat war ein fork aber danach bekomme ich so schwere Fehler das das Programm unbrauchbar ist.
Hat vielleicht noch irgend jemand eine Idee wie ich es anstellen könnte das es funktioniert?
Meine vermutung ist das ich irgendwie das Suchen und das Pulsen als Subprocess laufen lassen muss. So das der Button früher los läßt und das Pulsen überhaupt anzeigt.
Meine vermutung ist das ich irgendwie das Suchen und das Pulsen als Subprocess laufen lassen muss. So das der Button früher los läßt und das Pulsen überhaupt anzeigt.
Deine `on_search`-Methode wird beim Klicken auf den Button von gtk aufgerufen. Solange jetzt diese Methode ausgeführt wird, reagiert gtk nicht auf Events, löst keine aus und zeichnet die GUI auch nicht neu. Das bedeutet auch, dass solange keine mit `gobject.timeout_add` registrierten Timeout-Funktionen aufgerufen werden, folglich deine `bar_searching`-Methode nie aufgerufen wird.
Du könntest die Suche in einen Thread auslagen, dabei ist aber zu beachten, dass die wenigstens GUI-Toolkits, und dazu gehört auch gtk, es mögen, wenn man mit mehr als einem Thread auf die GUI zugreift. Du müsstest also immer vom gleichen Thread aus auf die GUI zugreifen.
Du könntest die Suche in einen Thread auslagen, dabei ist aber zu beachten, dass die wenigstens GUI-Toolkits, und dazu gehört auch gtk, es mögen, wenn man mit mehr als einem Thread auf die GUI zugreift. Du müsstest also immer vom gleichen Thread aus auf die GUI zugreifen.
Meinst du das so Trundle ? :
Falls du das so meinst, muss ich leider sagen das das Programm so hängt. Es friert ein.
Code: Alles auswählen
def on_search(self, data):
text = self.search_entry.get_text()
self.aur.clear_information()
gtk.gdk.threads_enter()
self.aur.search(text)
gtk.gdk.threads_leave()
if self.aur.is_package():
self.on_information()
else:
self.no_pack_dialog()
Mit dem `[mod]threading[/mod]`-Modul kann man neue Threads starten. Das könnte dann vllt so irgendwie aussehen:
Bevor man dann `gtk.main` aufruft, sollte man dann noch `gtk.gdk.threads_init` aufrufen.
Code: Alles auswählen
from threading import Thread
def search_function(text):
# Anstatt search_function eben die richtige Suchfunktion
import time
time.sleep(10)
def on_search(self, data):
text = self.search_entry.get_text()
search = Thread(target=search_function, args=[text])
search.start()
gobject.timeout_add(100, lambda: self.progressbar.pulse() or search.isAlive())
Hey super es klappt !!!
Ein Problem noch...... ich muss warten darauf das die Suche beendet ist. Weil je nachdem ob die Suche erfolgreich war folgen Funktionen.
Ich habe es schon mit os.wait() probiert aber das ist nur für forks wie mir scheint.
Ist es nun auch möglich auf den Thread zu warten ?
Ein Problem noch...... ich muss warten darauf das die Suche beendet ist. Weil je nachdem ob die Suche erfolgreich war folgen Funktionen.
Ich habe es schon mit os.wait() probiert aber das ist nur für forks wie mir scheint.
Ist es nun auch möglich auf den Thread zu warten ?
Das ginge schon (im konkreten Fall mit ``search.join()``). Aber dann wäre ja genau wieder das Problem, dass die GUI "blockiert" wird (eben weil die `on_search`-Methode erst nach geraumer Zeit wieder zurückkehrt) und du könntest den Thread auch einfach weglassen. Einfach die Funktionen im Suche-Thread aufrufen, nach der Suche eben. Jedoch dürfen die Funktionen dann nicht direkt auf die GUI zugreifen (weil anderer Thread), sondern müssen dies z.B. über `gobject.idle_add` tun.
Beispiel (angenommen, das steht in einer Klasse):
Beispiel (angenommen, das steht in einer Klasse):
Code: Alles auswählen
def suche(self, word):
# Such-Code eben
# Jetzt soll das ergebnis angezeigt werden
ergebnis = 'Spam'
gobject.idle_add(self.ausgabe, ergebnis)
def ausgabe(self, ergebnis):
# Hier könnte man jetzt auf die GUI zugreifen
self.resultentry.set_text(ergebnis)