wxGauge: Fortschritt einer Funktion anzeigen

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Benutzeravatar
Spaten
User
Beiträge: 52
Registriert: Samstag 27. Mai 2006, 11:35
Wohnort: Bremen
Kontaktdaten:

Sonntag 31. Dezember 2006, 12:15

Hallo zusammen!

Ich bin dabei ein Programm zu schreiben, welches Dateien verschlüsselt.
Der Algorythmus ist in ein Modul ausgelagert, die GUI ist im Hauptmodul
implementiert.
Ich habe eine Gauge, welche während des Verschlüsselns den Vortschritt
des Prozesses anzeigen soll.

Bild

Zum Verschlüsseln wird die zu verschlüsselnde Datei byteweise eingelesen
und wieder geschrieben.
Während dieses Prozesses müsste ich ja eigentlich Daten an die Gauge schicken.
Ich hab aber keine Ahnung wie. Hab schon an Threads gedacht,
so dass die beiden Sachen nebenherlaufen können. Aber wie sende ich den
Status an die Gauge?

Kann mir da jemand mit helfen?
Python-Version: 2.5
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Sonntag 31. Dezember 2006, 13:03

Spaten hat geschrieben:Hab schon an Threads gedacht
Hi Spaten!

Ein Thread ist hier sicher angebracht. Achte allerdings darauf, dass du NIEMALS (threadübergreifend) eine Funktion oder eine Methode eines anderen Threads ohne den Umweg über ``CallAfter`` aufrufst. Die GUI läuft sozusagen in einem eigenständigen Thread. Wenn du vom arbeitenden Thread aus etwas an der GUI ändern möchtest, dann rufe die Funktion, die etwas an der GUI ändert, über ``wx.CallAfter`` auf. Damit hast du automatisch eine Threadtrennung. Wenn du das nicht machst, dann wird dein Programm abstürzen, nicht plattformunabhängig arbeiten oder einfach nur unerwünschte Nebenwirkungen zeigen. ;-)

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import wx
import time
from thread import start_new_thread

wx.SetDefaultPyEncoding("iso-8859-1")


class MyFrame(wx.Frame):
    
    def __init__(self, parent = None, id = -1, title = "Worker"):
        
        wx.Frame.__init__(self, parent, id, title)
        
        panel = wx.Panel(self)
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox)
        
        gauge = wx.Gauge(panel, size = (300, -1))
        vbox.Add(gauge, 0, wx.EXPAND | wx.ALL, 10)
        self.gauge = gauge
        
        cmd = wx.Button(panel, -1, "Start")
        vbox.Add(cmd, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 10)
        cmd.Bind(wx.EVT_BUTTON, self.start_work)
        self.cmd = cmd
        
        panel.Fit()
        self.Fit()
        self.SetSizeHintsSz(self.GetSizeTuple())
    
    
    def set_gauge_value(self, value):
        
        # Hier wird über einen WICHTIGEN (!!!) Umweg über ``CallAfter``
        # ``SetValue`` aufgerufen.
        assert(0 <= int(value) <= 100)
        wx.CallAfter(self.gauge.SetValue, value)
    
    
    def on_process_exit(self):
        
        # Hier wird über einen WICHTIGEN (!!!) Umweg über ``CallAfter``
        # ``Enable`` aufgerufen.
        wx.CallAfter(self.cmd.Enable, True)
    
    
    def worker_thread(self, process_display_function, process_exit_function):
        
        # hier wird gearbeitet
        for i in range(100):
            process_display_function(i)
            time.sleep(0.04)
        
        process_exit_function()
    
    
    def start_work(self, event):
        
        self.cmd.Disable()
        start_new_thread(self.worker_thread, (self.set_gauge_value, self.on_process_exit))
    

def main():
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
mfg
Gerold
:-)

Edit: So angepasst, dass die aufgerufene Funktion auch in einem anderen Modul sein kann.
Zuletzt geändert von gerold am Sonntag 31. Dezember 2006, 17:34, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
Spaten
User
Beiträge: 52
Registriert: Samstag 27. Mai 2006, 11:35
Wohnort: Bremen
Kontaktdaten:

Sonntag 31. Dezember 2006, 15:56

ah danke, das ist ungefähr das, was ich wollte,
aber wie kann ich das machen, wenn die arbeitende methode in einem anderen modul liegt?

Code: Alles auswählen

import modul

class Gui(wx.Frame):
   def __init___(self):
        wx.Frame.__init__(self, None, -1):
        self. bar = wx.Gauge(self,  -1, 100, wx.Point(80,280), wx.Size(250, -1), wx.GA_SMOOTH)
   def workHere(self, event):
        zuweisung = modul.Klasse(parameter)
        start_new_thread(zuweisung.methode, ())

#####################
#####################
##Im anderen Modul:

class Klasse(object):
   def __init__(self):
        pass
   def methode():
        # hier wird gearbeitet...
        wx.CallAfter(???????, value)
ist ziemlich nett von dir, dass du mir immer hilfst! Vielen Dank!
Python-Version: 2.5
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Sonntag 31. Dezember 2006, 17:48

Spaten hat geschrieben:aber wie kann ich das machen, wenn die arbeitende methode in einem anderen modul liegt?
[...]
ist ziemlich nett von dir, dass du mir immer hilfst! Vielen Dank!
Hi Spaten!

Ach, das trifft sich einfach immer nur zufällig so, dass du Fragen stellst, auf die ich eine Antwort geben kann und mich das Thema der Frage gerade genug interessiert, dass ich mich dazu entschließe, dir eine Antwort zu schreiben. Würdest du eine Frage z.B. zu Tkinter stellen, dann würde ich sie wahrscheinlich nicht einmal durchlesen. :-)

Was deine Frage angeht. -- Wenn du der Methode/Funktion, die die Arbeit erledigt, eine Referenz zu einer Methode/Funktion mitgibst, die sich um das Ändern des Gauge-Value kümmert, dann kann die arbeitende Methode überall sein.

Zur Demonstration, habe ich mein oben gezeigtes Beispiel leicht verändert!

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
Spaten
User
Beiträge: 52
Registriert: Samstag 27. Mai 2006, 11:35
Wohnort: Bremen
Kontaktdaten:

Dienstag 2. Januar 2007, 23:28

ah danke, jetzt kann ich mir da ungefähr was drunter vorstellen...
ich probiers morgen nochmal aus.
Python-Version: 2.5
Antworten