Seite 1 von 1
Verfasst: Mittwoch 24. Mai 2006, 14:40
von DatenMetzgerX
Merci.... werde mri da sspäter mal genauer ansehen
Noch eine Frage (weiss ich habe viele ^^)
Ich habe ein frame welches beim start des Backups geladen wird.
Ich setzte in das (der die???) TextCtrl während des Backups weitere Zeilen rein und aktualisiere die Gauge.
Nur wenn jemand auf die Idee kommt das Fenster zu wechseln oder das Fenster zu verschieben / vergrössern bleibt der Inhalt für immer weiss
Sehr unpraktisch bei langen Backups...
vorher...
nachher
...
Verfasst: Mittwoch 24. Mai 2006, 14:46
von pr0stAta
Bei solch wirklich Programmspezifischen Fragen wäre es
vielleicht das beste, wenn du uns den relevanten Code zeigen
würdest
Verfasst: Mittwoch 24. Mai 2006, 15:03
von DatenMetzgerX
Code: Alles auswählen
def Copy(strDatei,strDateiroh, strZiel, Log, frame, counter=0):
#Nur os.sep + Ordner /Dateiname bleibt zurueck
strDatei = string.replace(strDatei,strDateiroh, '')
counter+=1
#frame.progress.Update(counter)
frame.progress.SetValue(counter)
if not os.path.isdir(strDateiroh + strDatei): #ueperpruefen ob es ein Verzeichnis ist
#Versuche Datei zu Kopieren, Wenn es nicht funktioniert ins Log File schreiben
try:
#print strDateiroh + strDatei
frame.SetText(strDateiroh + strDatei)
shutil.copy2(strDateiroh + strDatei, strZiel + strDatei)
#if os.system('copy "' + strDateiroh + strDatei + '" "' + strZiel + strDatei + '"') !=0:
# Log.write("\n\nDatei %s konnte nicht kopiert werden" %(strDateiroh + strDatei))
except:
try:
shutil.copy(strDateiroh + strDatei, strZiel + strDatei)
except:
Log.write("\n\nDatei %s konnte nicht gesichert werden"%(strDateiroh + strDatei))
#Bei Verzeichnis
else:
try:
ToCreate = (strZiel + strDatei) #Welches Verzeichnis angelegt werden muss
if not os.path.exists(ToCreate): #Wenn es nicht existiert neu anlegen
os.mkdir(ToCreate)
listDir = os.listdir(strDateiroh +os.sep + strDatei) #Inhalt des Verzeichnisses ausgeben
for element in listDir: #Fuer jede Datei / Element selbstaufruf
counter=Copy(strDateiroh + strDatei + os.sep + element, strDateiroh + strDatei, strZiel + strDatei, Log, frame, counter) #Selbst aufruf fuer Unterverzeichnise
except:
Log.write("\nOrdner %s konnte samt Unterverzeichnisen / Dateien nicht\ngesichert werden" %(strDatei))
return counter
Nicht der schönste code ^^
Code: Alles auswählen
class Frame(wx.Frame):
def __init__(self, Files, parent="None", id=-1, title="Backup"):
wx.Frame.__init__(self, parent, id, title)
self.panel =wx.Panel(self)
Sizer = wx.FlexGridSizer(2, 0)
intFiles=0
for File in Files:
intFiles+=CountFiles(File)
#self.progress = wx.ProgressDialog("Backup", "", intFiles, None, wx.PD_AUTO_HIDE | wx.PD_ELAPSED_TIME | wx.PD_REMAINING_TIME)
#__init__(self, parent, id, pos, size, style, validator, name)
self.progress=wx.Gauge(self.panel, id)
self.progress.SetRange(intFiles)
self.text = wx.TextCtrl(self.panel, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
Sizer.AddGrowableRow(0)
Sizer.AddGrowableRow(1)
Sizer.Add(self.progress, 0, wx.EXPAND | wx.ALL, 10)
Sizer.Add(self.text, 0, wx.EXPAND | wx.BOTTOM | wx.RIGHT | wx.LEFT, 10)
self.progress.SetMinSize((300,30))
self.text.SetMinSize((600,300))
self.panel.SetSizer(Sizer)
Sizer.Fit(self)
Sizer.SetSizeHints(self)
self.Show()
def SetText(self, text):
self.text.WriteText('\n' + text)
Code: Alles auswählen
elif intModus == 0 and strProg != 'subversion':
Log = open(strZiel + os.sep + "log.txt", "w")
Log.close
#wxPython Applikation starten
#__init__(self, parent, id, pos, size, style, name)
app = wx.PySimpleApp()
#Frame setzen
frame = BackupFunctions.Frame(Files, None, -1, "Backup")
#frame als oberstes Fenster setzen
#Kein frame.Show(), frame soll nicht angezeigt werden
app.SetTopWindow(frame)
#Dateien Sichern
for File in Files:
BackupFunctions.Copy(File,File, strZiel, Log, frame)
#Fenster schliessen
frame.Destroy()
Muss ich evth mit Threads arbeiten :s
app.MainLoop() habe ich nicht gemacht weil ich keinen Input des Benutzer möchte
Verfasst: Mittwoch 24. Mai 2006, 17:42
von gerold
Ich habe aus deiner Frage ein neues Thema gemacht.
mfg
Gerold
Verfasst: Mittwoch 24. Mai 2006, 19:12
von DatenMetzgerX
Merciii....
Aber glaube habe die Lösung auf mein Problem... Threats auch wenn ich die nicht mag ^^
Verfasst: Mittwoch 24. Mai 2006, 20:05
von gerold
DatenMetzgerX hat geschrieben:Threats auch wenn ich die nicht mag ^^
Du hast sicher recht. Das dürfte die einfachste Lösung sein..
mfg
Gerold
Verfasst: Donnerstag 25. Mai 2006, 00:18
von Joghurt
Evtl. reicht es auch, periodisch
aufzurufen
Verfasst: Donnerstag 25. Mai 2006, 22:13
von DatenMetzgerX
Habe mich mal ein wenig mit Threads herumgeschlagen
...
Was ich nicht geschafft habe ist app.MainLoop() in einem eigenen Thread laufen zu lassen
Code: Alles auswählen
class guiThread(threading.Thread):
def __init__(self, app):
self.app = app
threading.Thread.__init__(self)
def run(self):
self.app.MainLoop()
Das Fenster bleibt einfach weiss....
Das Andere Problem ist...
Eigentlich wollte ich das Frame automatisch nach dem Backup schliessen, aber wie. Über frame.Destroy() freut sich das app.MainLoop() nicht.
Deshalbt versuchte ich auch den Loop in einen eigenen Thread zu bringen dann häte ich nämlich prüfen können
Code: Alles auswählen
while corethread.isAlive() or guiThread.isAlive():
if guiThread.isAlive():
guiThread.abort() #Weiss den exit /cancel Befehl gerade nicht...
if corethread.isAlive():
corethread.abort()
Und dann hätte ich das MainLoop weg, vieleicht ein wenig brutal aber was solls, geht ja eh nicht
Jemand eine Idee
Edit:// gibts so was wie ein Statusdialog, den ich einblenden könnte während die Files gezählt werden?
Verfasst: Freitag 26. Mai 2006, 09:01
von gerold
DatenMetzgerX hat geschrieben:Was ich nicht geschafft habe ist app.MainLoop() in einem eigenen Thread laufen zu lassen
Hi DatenMetzgerX!
Das ist sicher die falsche Weise so etwas anzugehen.
**app.mainloop()** kümmert sich um die Anzeige von Fenstern und das Abarbeiten von Events. **app** ist also ein eigener Thread.
Lass den dafür vorgesehenen Thread, also **app**, um die Anzeige kümmern und lagere die Arbeit in einen eigenen Thread aus. Allerdings musst du den arbeitenden Thread komplett unabhängig von der GUI machen. Wenn es eine neue Statusmeldung gibt, dann kann der arbeitende Thread eine Meldung an den GUI-Thread schicken. Der GUI-Thread kümmert sich dann darum, dass eine entsprechende Meldung angezeigt wird.
http://wiki.wxpython.org/index.cgi/LongRunningTasks
mfg
Gerold
Verfasst: Freitag 26. Mai 2006, 18:35
von DatenMetzgerX
Das mit den Threads habe ich zum Teil hinbekommen. Nur wenn der Benutzer nun die Gui beendet. Wie kill ich den anderen Thread???
thread.stop(), thread.kill() und thread.cancel() ging nicht. Einen Befehl habe ich mit Googlen auch noch nicht herausgebracht
Code: Alles auswählen
#Main
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = BackupFunctions.Frame(None, -1, "Backup")
app.SetTopWindow(frame)
Appli = CopyThread(app,frame)
frame.Bind(wx.EVT_CLOSE, Appli.abort)
Appli.start()
app.MainLoop()
Code: Alles auswählen
class CopyThread(threading.Thread):
def __init__(self, app, frame):
threading.Thread.__init__(self)
self.app = app
self.frame = frame
def run (self):
Main()
app.ExitMainLoop()
frame.Destroy()
def abort(self, event):
self.stop()
Das ganze ist z.T ein wenig ein drucheinander, weil ich am Anfang noch zu wenig mit Funktionen und Klassengearbeitet habe
Aber wie ist der Befehl um einen Thread zu killen.
Verfasst: Samstag 27. Mai 2006, 14:11
von gerold
Hier ein Beispiel. Nur unter Linux getestet.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import wx
import threading
import time
# Define notification event for thread completion
EVT_NEWMESSAGE_ID = wx.NewId()
EVT_STOP_ID = wx.NewId()
def EVT_NEWMESSAGE(win, func):
"""
Define NewMessage Event.
"""
win.Connect(-1, -1, EVT_NEWMESSAGE_ID, func)
def EVT_STOP(win, func):
"""
Define NewMessage Event.
"""
win.Connect(-1, -1, EVT_STOP_ID, func)
class NewMessageEvent(wx.PyEvent):
"""
Simple event
"""
def __init__(self, message):
"""
Init Event.
"""
wx.PyEvent.__init__(self)
self.SetEventType(EVT_NEWMESSAGE_ID)
self.message = message
class StopEvent(wx.PyEvent):
"""
Simple event
"""
def __init__(self):
"""
Init Event.
"""
wx.PyEvent.__init__(self)
self.SetEventType(EVT_STOP_ID)
class MyFrame(wx.Frame):
"""
Hauptframe
"""
def __init__(
self, parent = None, title = "Hauptframe", size = (400, 300)
):
# Frame initialisieren
wx.Frame.__init__(self, parent, -1, title)
# Ein Panel als Grundlage
panel = wx.Panel(self)
# Ein vertikaler Boxsizer zum Anordnen
vb = wx.BoxSizer(wx.VERTICAL)
panel.SetSizer(vb)
# Ein Textfeld für die Ausgabe der Statusmeldungen (read only)
self.messages = wx.TextCtrl(
panel, -1,
style = wx.TE_AUTO_SCROLL | wx.TE_LINEWRAP |
wx.TE_MULTILINE | wx.TE_READONLY
)
vb.Add(self.messages, 1, wx.ALL | wx.EXPAND, 5)
# Buttonleiste
hb = wx.BoxSizer(wx.HORIZONTAL)
vb.Add(hb, 0, wx.EXPAND)
# Start
start_btn = wx.Button(panel, -1, "Start")
hb.Add(start_btn, 1, wx.ALIGN_CENTER_HORIZONTAL| wx.ALL, 5)
start_btn.Bind(wx.EVT_BUTTON, self.start_thread)
# Stopp
stopp_btn = wx.Button(panel, -1, "Stopp")
hb.Add(stopp_btn, 1, wx.ALIGN_CENTER_HORIZONTAL| wx.ALL, 5)
stopp_btn.Bind(wx.EVT_BUTTON, self.stop_thread)
# Thread-Variablen vorbereiten
self.myworkerthread = None
self.thread_started = False
# NewMessage-Event binden
EVT_NEWMESSAGE(self, self.add_message)
# Stop-Event binden
EVT_STOP(self, self.stop_me)
def add_message(self, event = None, message = None):
"""
Fügt an den Text eine neue Zeile mit der neuen Nachricht an.
"""
if event:
message = str(event.message)
if len(self.messages.GetValue()) > 0:
message = "\n" + message
self.messages.AppendText(message)
self.messages.ScrollLines(10)
def start_thread(self, event = None):
"""
Startet den Thread
"""
# Prüfen ob der Thread schon läuft
if self.thread_started:
self.add_message(message = u"Der Thread läuft bereits...")
return
# Thread initialisieren
self.myworkerthread = MyWorkerThread(self)
# Thread starten
self.myworkerthread.start()
# Variable setzen und Nachricht ausgeben
self.thread_started = True
self.add_message(message = u"Der Thread wurde soeben gestartet...")
def stop_thread(self, event = None):
"""
Stoppt den Thread
"""
if self.myworkerthread:
self.myworkerthread.stop()
self.thread_started = False
self.add_message(message = "Der Thread wurde soeben unterbrochen...")
else:
self.add_message(message = "Kein Thread aktiv...")
def stop_me(self, event = None):
"""
Fragt ob beendet werden soll und beendet bei Ja.
"""
retval = wx.MessageBox(
u"Möchten Sie jetzt beenden?",
"Beenden",
wx.YES_NO | wx.NO_DEFAULT | wx.CENTER ,
self
)
if retval == wx.YES:
self.Close()
class MyWorkerThread(threading.Thread):
"""
Diese Klasse soll Arbeit erledigen, aber nichts anzeigen.
"""
def __init__(self, notify_window):
"""
Initialisiert die Klasse und
übernimmt das Objekt, an das später die Events geschickt werden.
"""
threading.Thread.__init__(self)
self._notify_window = notify_window
self.stop_event = threading.Event()
def run(self):
"""
Thread-Hauptprozedur
"""
while True:
# Wenn das threading.Event (stop_event) gesetzt wurde --> abbrechen.
if self.stop_event.isSet():
# Thread stoppen
break
# Event an den Frame schicken
wx.PostEvent(
self._notify_window, NewMessageEvent(time.strftime("%H:%M:%S"))
)
time.sleep(2)
# Event zum Stoppen an Frame schicken
wx.PostEvent(self._notify_window, StopEvent())
def stop(self):
"""
Versucht den Thread zu unterbrechen. Dazu wird das
threading.Event (stop_event) gesetzt. Der Thread muss sich immer
selber abbrechen. Deshalb der Umweg über ein threading.Event.
"""
self.stop_event.set()
def main():
"""
Hauptprozedur
"""
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
frame.Center()
app.MainLoop()
if __name__ == "__main__":
main()
mfg
Gerold
Verfasst: Samstag 27. Mai 2006, 14:20
von gerold
So finde ich es fast noch ein bischen einfacher. Ohne die beiden Funktionen EVT_NEWMESSAGE und EVT_STOP.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import wx
import threading
import time
# NewMessageEvent
EVT_NEWMESSAGE_ID = wx.NewId()
class NewMessageEvent(wx.PyEvent):
"""
Simple event
"""
def __init__(self, message):
"""
Init Event.
"""
wx.PyEvent.__init__(self)
self.SetEventType(EVT_NEWMESSAGE_ID)
self.message = message
# StopEvent
EVT_STOP_ID = wx.NewId()
class StopEvent(wx.PyEvent):
"""
Simple event
"""
def __init__(self):
"""
Init Event.
"""
wx.PyEvent.__init__(self)
self.SetEventType(EVT_STOP_ID)
class MyFrame(wx.Frame):
"""
Hauptframe
"""
def __init__(
self, parent = None, title = "Hauptframe", size = (400, 300)
):
# Frame initialisieren
wx.Frame.__init__(self, parent, -1, title)
# Ein Panel als Grundlage
panel = wx.Panel(self)
# Ein vertikaler Boxsizer zum Anordnen
vb = wx.BoxSizer(wx.VERTICAL)
panel.SetSizer(vb)
# Ein Textfeld für die Ausgabe der Statusmeldungen (read only)
self.messages = wx.TextCtrl(
panel, -1,
style = wx.TE_AUTO_SCROLL | wx.TE_LINEWRAP |
wx.TE_MULTILINE | wx.TE_READONLY
)
vb.Add(self.messages, 1, wx.ALL | wx.EXPAND, 5)
# Buttonleiste
hb = wx.BoxSizer(wx.HORIZONTAL)
vb.Add(hb, 0, wx.EXPAND)
# Start
start_btn = wx.Button(panel, -1, "Start")
hb.Add(start_btn, 1, wx.ALIGN_CENTER_HORIZONTAL| wx.ALL, 5)
start_btn.Bind(wx.EVT_BUTTON, self.start_thread)
# Stopp
stopp_btn = wx.Button(panel, -1, "Stopp")
hb.Add(stopp_btn, 1, wx.ALIGN_CENTER_HORIZONTAL| wx.ALL, 5)
stopp_btn.Bind(wx.EVT_BUTTON, self.stop_thread)
# Thread-Variablen vorbereiten
self.myworkerthread = None
self.thread_started = False
# NewMessage-Event und Stop-Event binden
self.Connect(-1, -1, EVT_NEWMESSAGE_ID, self.add_message)
self.Connect(-1, -1, EVT_STOP_ID, self.stop_me)
def add_message(self, event = None, message = None):
"""
Fügt an den Text eine neue Zeile mit der neuen Nachricht an.
"""
if event:
message = str(event.message)
if len(self.messages.GetValue()) > 0:
message = "\n" + message
self.messages.AppendText(message)
self.messages.ScrollLines(10)
def start_thread(self, event = None):
"""
Startet den Thread
"""
# Prüfen ob der Thread schon läuft
if self.thread_started:
self.add_message(message = u"Der Thread läuft bereits...")
return
# Thread initialisieren
self.myworkerthread = MyWorkerThread(self)
# Thread starten
self.myworkerthread.start()
# Variable setzen und Nachricht ausgeben
self.thread_started = True
self.add_message(message = u"Der Thread wurde soeben gestartet...")
def stop_thread(self, event = None):
"""
Stoppt den Thread
"""
if self.myworkerthread:
self.myworkerthread.stop()
self.thread_started = False
self.add_message(message = "Der Thread wurde soeben unterbrochen...")
else:
self.add_message(message = "Kein Thread aktiv...")
def stop_me(self, event = None):
"""
Fragt ob beendet werden soll und beendet bei Ja.
"""
retval = wx.MessageBox(
u"Möchten Sie jetzt beenden?",
"Beenden",
wx.YES_NO | wx.NO_DEFAULT | wx.CENTER ,
self
)
if retval == wx.YES:
self.Close()
class MyWorkerThread(threading.Thread):
"""
Diese Klasse soll Arbeit erledigen, aber nichts anzeigen.
"""
def __init__(self, notify_window):
"""
Initialisiert die Klasse und
übernimmt das Objekt, an das später die Events geschickt werden.
"""
threading.Thread.__init__(self)
self._notify_window = notify_window
self.stop_event = threading.Event()
def run(self):
"""
Thread-Hauptprozedur
"""
while True:
# Wenn das threading.Event (stop_event) gesetzt wurde --> abbrechen.
if self.stop_event.isSet():
# Thread stoppen
break
# Event an den Frame schicken
wx.PostEvent(
self._notify_window, NewMessageEvent(time.strftime("%H:%M:%S"))
)
time.sleep(2)
# Event zum Stoppen an Frame schicken
wx.PostEvent(self._notify_window, StopEvent())
def stop(self):
"""
Versucht den Thread zu unterbrechen. Dazu wird das
threading.Event (stop_event) gesetzt. Der Thread muss sich immer
selber abbrechen. Deshalb der Umweg über ein threading.Event.
"""
self.stop_event.set()
def main():
"""
Hauptprozedur
"""
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
frame.Center()
app.MainLoop()
if __name__ == "__main__":
main()
mfg
Gerold