Hallo,
ich versuche nun seit Stunden mit der ToasterBox-Klasse ein Popup zu erzeugen, was soweit auch prima klappt. Nur kann ich das ganze insgesamt nicht in mein Programm integrieren.
Eigentlich läuft die gesamte "GUI" über curses und es wird ein Netzwerkprotokoll ausgelesen und ich möchte nur, dass bei bestimmten Situationen über wxPython ein grafisches Popup (eben eine Toasterbox) erscheint. Probleme stellt offenbar jedoch der wx.Timer dar, denn ohne die MainLoop() von wx.PySimpleApp() läuft dieser nicht. Ich kann jedoch die MainLoop() nicht sinnvoll integrieren, da ich den Code des Programms nicht hauptlastig auf wxPython legen möchte.
Ich habe ebenso versucht, mit Threads einfach die ToasterBox aufzurufen und nach einem Timer (time.sleep(...)) mit box.GetToasterBoxWindow().ScrollDown() die Box zu schließen. Aber auch das führte zu wenig Erfolg seitens ScrollDown().
Das nächste Problem ist, dass durchaus mehrere ToasterBox'es erzeugt werden können, je nach Daten, die empfangen werden.
Daher meine Fragen:
Kann ich irgendwie die MainLoop() in einem Thread laufen lassen und erst danach(!) die ToasterBoxen initialisieren? (Dafür bräuchte ich aber ein nicht sichtbares Window, das ständig präsent ist, oder? Sonst kommt die MainLoop ja sofort zurück....)
In meinen simplen Versuchen ging's nicht (das nachträgliche Initialisieren: Keine Box zu sehen) und die Xlib verabschiedete sich beim Threading auch mit einem Xlib: unexpected async reply
Wie kann ich das überhaupt sinnvoll umsetzen? Ich will nicht mehr als diese Popups, für alles andere möchte und will ich kein wxPython verwenden. Gibt es vielleicht Alternativen, mit denen mach auch grafisch anspruchsvolle Popups machen kann?
Bitte befruchtet mich gedanklich
Grüße
Simples Popup erzeugen
Hallo,
Den Thread über das threading oder das thread-Modul? Und wie erzeuge ich die Queue?
Grüße
hört sich gut an, aber ich habe mit wxPython leider bisher wenig Erfahrung.veers hat geschrieben: Knall den wx mainloop in einen eigenen Thread, häng den wx mainloop an eine Queue.
Wenn immer du ein Popup brauchst fügst du ein neues Element in die Queue.
Den Thread über das threading oder das thread-Modul? Und wie erzeuge ich die Queue?
Grüße
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo Twix!Twix hat geschrieben:Eigentlich läuft die gesamte "GUI" über curses
[...]
ich möchte nur, dass bei bestimmten Situationen über wxPython ein grafisches Popup (eben eine Toasterbox) erscheint.
[...]
Ich habe ebenso versucht, mit Threads einfach die ToasterBox aufzurufen und nach einem Timer (time.sleep(...)) mit box.GetToasterBoxWindow().ScrollDown() die Box zu schließen.
[...]
Das nächste Problem ist, dass durchaus mehrere ToasterBox'es erzeugt werden können, je nach Daten, die empfangen werden.
[...]
Kann ich irgendwie die MainLoop() in einem Thread laufen lassen und erst danach(!) die ToasterBoxen initialisieren?
[...]
Wie kann ich das überhaupt sinnvoll umsetzen? Ich will nicht mehr als diese Popups, für alles andere möchte und will ich kein wxPython verwenden.
Das ist schwieriger als man glaubt. Es ist wichtig, dass wxPython nur in **einem** Thread läuft. Also muss das Initialisieren der wxPySimpleApp im gleichen Thread laufen wie später die MainLoop. An der MainLoop blockiert wxPython so lange, bis ein wxPython-Event ausgelöst wird.
Das bedeutet, du brauchst einen Hauptthread (das normale Programm) für dein Curses-Programm und einen Thread für die wxPython-GUI
Der Hauptthread gibt dann die Anweisung über ``wx.CallAfter()`` (damit wird die Threadtrennung garantiert) an den wxPython-Thread weiter. Und dieser wxPython-Thread kann dann unabhängig vom Hauptthread arbeiten und ein paar Sekunden lang eine ToasterBox einblenden.
Ich glaube nicht, dass du den Umweg über eine Queue brauchst, aber ich werde mich mal ein wenig spielen. Vielleicht finde ich etwas raus.
mfg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Ich habe mich ein wenig gespielt und das ist dabei raus gekommen:
Ich hoffe, dass dieser Code auch unter Linux funktioniert. Das wollte ich jetzt nicht testen.
mfg
Gerold
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
import wx
import ToasterBox as TB # http://xoomer.alice.it/infinity77/eng/freeware.html#toasterbox
import threading
import time
wx.SetDefaultPyEncoding("iso-8859-15")
class MyCursesGui(object):
def __init__(self, wx_thread):
while True:
self.show_menu()
retval = raw_input()
if retval == "Q":
break
else:
wx_thread.show_toasterbox(retval)
# Fertig
print "Das Programm wird beendet."
def show_menu(self):
print
print "Q - Beendet das Programm"
print
print "Gib etwas ein und druecke Enter. Dann wird es in der ToasterBox angezeigt."
class MyWxPythonGui(threading.Thread):
def run(self):
"""
Hier läuft der Thread (hier und in allen von hier aufgerufenen Methoden).
Wird mit ``self.start()`` auf gerufen.
"""
self.app = wx.PySimpleApp()
self.wait_frame = wx.Frame(None)
self.app.MainLoop()
print "MainLoop fertig"
def stop(self):
# wx.CallAfter ist wichtig für die Threadtrennung. Ein Kommando darf niemals
# direkt von einem Thread an einen anderen Thread gegeben werden.
wx.CallAfter(self.wait_frame.Close)
time.sleep(0.5)
wx.CallAfter(self.app.ExitMainLoop)
def show_toasterbox(self, text):
wx.CallAfter(self._show_toasterbox_threadsafe, text)
def _show_toasterbox_threadsafe(self, text):
tb = TB.ToasterBox(self.wait_frame)
tb.SetPopupPosition((800, 600))
tb.SetPopupText(text)
tb.SetPopupPauseTime(4000)
tb.Play()
def main():
wx_thread = MyWxPythonGui()
wx_thread.start()
MyCursesGui(wx_thread)
wx_thread.stop()
wx_thread.join() # warten bis die MainLoop fertig ist
if __name__ == "__main__":
main()
mfg
Gerold
Zuletzt geändert von gerold am Freitag 22. Juni 2007, 14:16, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Hallo!
Erst mal danke für die schnelle Hilfe und Mühe
app = wx.PySimpleApp() und
app.MainLoop()
Wenn ich das wie oben aufrufe, beendet das Programm natürlich sofort, da die MainLoop ja nichts "zu tun" hat.
Viele Grüße
Erst mal danke für die schnelle Hilfe und Mühe
Das kann man laut sagengerold hat geschrieben: Das ist schwieriger als man glaubt.
Kann ich durchaus verstehen, aber mir fehlt der Zwischenschritt zwischenEs ist wichtig, dass wxPython nur in **einem** Thread läuft. Also muss das Initialisieren der wxPySimpleApp im gleichen Thread laufen wie später die MainLoop. An der MainLoop blockiert wxPython so lange, bis ein wxPython-Event ausgelöst wird.
app = wx.PySimpleApp() und
app.MainLoop()
Wenn ich das wie oben aufrufe, beendet das Programm natürlich sofort, da die MainLoop ja nichts "zu tun" hat.
Wärst du so nett und könntest mir hier ein ganz simples Beispiel zeigen? Mir fehlt dafür gerade etwas die Vorstellungskraft :-/Der Hauptthread gibt dann die Anweisung über ``wx.CallAfter()`` (damit wird die Threadtrennung garantiert) an den wxPython-Thread weiter.
Viele Grüße
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo Twix!Twix hat geschrieben:Wärst du so nett und könntest mir hier ein ganz simples Beispiel zeigen?
...ist einen Beitrag ober dir.
mfg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
(Sorry, das ich mal kurz meinen Senf dazu gebe ... in der Hoffnung, das nicht zu viel Unsinn dabei ist ...)
Zwischen und gehört genau der Code, der ein Fenster erzeugt und anzeigt. Die MainLoop() übernimmt dann die Verarbeitung der Ereignisse.
Sobald das Fenster geschlossen wird, endet auch die MainLoop().
So weit ich weiss, ist dieses Verhalten normal ...Twix hat geschrieben: app = wx.PySimpleApp() und
app.MainLoop()
Wenn ich das wie oben aufrufe, beendet das Programm natürlich sofort, da die MainLoop ja nichts "zu tun" hat.
Zwischen
Code: Alles auswählen
app = wx.PySimpleApp()
Code: Alles auswählen
app.MainLoop()
Sobald das Fenster geschlossen wird, endet auch die MainLoop().
Hallo Gerold,gerold hat geschrieben:Ich habe mich ein wenig gespielt und das ist dabei raus gekommen:
[...]
Ich hoffe, dass dieser Code auch unter Linux funktioniert. Das wollte ich jetzt nicht testen.
vielen Danke für deine schnelle und umfassende Bemühung! Es funktioniert wunderbar und genauso, wie ich es mir vorgestellt hatte!
Besten Dank!