Seite 1 von 1

Throbber wird nicht richtig angezeigt [SOLVED]

Verfasst: Montag 3. Juli 2006, 15:34
von Steffen
Absicht:
Ich möchte in meinem Programm eine längere Datenübertragung ausführen (ca. 2min) und brauche deshalb einen Throbber, der während dieser Zeit angezeigt wird. Stellvertretend für die Datenübertragung habe ich im nachfolgenden Code wx.Sleep(10) verwendet, da auch meine Datenübertragung aus einer einzelnen Funktion besteht, die das Hauptprogramm stillstehen lässt.

Problem:
Der Throbber bleibt während der Datenübertragung weiß (wird nicht aktualisiert), obwohl dieser ja eigentlich in einem eigenen Thread laufen müsste!?

Kann mir jemand sagen, wo der Fehler liegt?

Code: Alles auswählen

import wx
import wx.lib.throbber as throb
import throbImages
#
if __name__=="__main__":
    def on_start_transfer(event):
        images = [throbImages.catalog[i].getBitmap()
                  for i in throbImages.index]
        my_throbber = throb.Throbber(throb_frame,-1,images)
        #
        throb_frame = wx.Frame(None,-1, size = (35,35), style = wx.SIMPLE_BORDER)
        throb_frame.Show()
        #
        my_throbber.Start()
        throb_frame.MakeModal(True)
        wx.Sleep(10) # Stands for transfer process.
        throb_frame.MakeModal(False)
    #
    app = wx.PySimpleApp()
    frame = wx.Frame(None)
    btn = wx.Button(frame,-1,'Start')
    #
    frame.Bind(wx.EVT_BUTTON, on_start_transfer, btn)
    #
    frame.Show()
    #
    app.MainLoop()

Re: Throbber wird nicht richtig angezeigt

Verfasst: Montag 3. Juli 2006, 18:05
von gerold
Hi Steffen!

Unterbrich niemals durch ein "sleep()" den app.MainLoop.
Da ist nichts mit eigenem Thread und so. Wenn du den MainLoop unterbrichst, dann passiert gar nichts mehr.

Wenn sich während längerer Prozesse noch etwas rühren soll, oder Zwischenstände angezeigt werden sollen, dann **muss** man die Arbeit in einen eigenen Thread auslagern. Allerdings darf dieser ausgelagerte Arbeits-Thread nicht direkt mit dem Haupt-Thread (MainLoop) kommunizieren. Die einfachste Art, wie der arbeitende Thread doch noch mit dem Haupt-Thread kommunizieren kann, ist über die Funktion "wx.CallAfter()". Diese Funktion kümmert sich um die Trennung der Threads.

Hier ein Beispiel, das ich allerdings nur unter Windows getestet habe.

Code: Alles auswählen

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

import wx
import wx.lib.throbber
import throbImages # Muss aus dem Demo-Ordner in den Projektordner kopiert werden
import thread
import time


class MyFrame(wx.Frame):
    """
    Hauptformular
    """
    
    def __init__(self, parent = None, id = -1, title = "Throbber-Worker"):
        """
        Initialisiert den Frame
        """
        
        wx.Frame.__init__(self, parent, id, title)
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        
        panel = wx.Panel(self)
        panel.SetSizer(vbox)
        
        images = [
            throbImages.catalog[i].getBitmap()
            for i in throbImages.index
            if i not in ['eclouds', 'logo']
        ]
        
        self.throb = wx.lib.throbber.Throbber(panel, -1, images)
        vbox.Add(self.throb, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5)
        
        self.btn_start = wx.Button(panel, -1, "Start")
        vbox.Add(self.btn_start, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5)
        self.btn_start.Bind(wx.EVT_BUTTON, self.OnStart)
        
        panel.Fit()
        self.SetVirtualSize(panel.GetSize())
        self.Fit()
        self.SetSizeHintsSz(self.GetSize())
        
        self.Center()
        self.Show()
    
    
    def my_worker(self):
        """
        Diese Funktion wird in einem eigenen Thread ablaufen
        """
        
        wx.CallAfter(self.throb.Start) # Aufruf über Thread-Grenze hinweg.
        wx.CallAfter(self.btn_start.Enable, False) # Aufruf über Thread-Grenze hinweg.
        
        time.sleep(10)
        
        wx.CallAfter(self.throb.Stop) # Aufruf über Thread-Grenze hinweg.
        wx.CallAfter(self.btn_start.Enable, True) # Aufruf über Thread-Grenze hinweg.


    def OnStart(self, event):
        """
        Startet den eigenständigen Thread
        """
        
        thread.start_new(self.my_worker, ())


if __name__ == "__main__":
    app = wx.PySimpleApp()
    myframe = MyFrame()
    app.MainLoop()
mfg
Gerold
:-)

Re: Throbber wird nicht richtig angezeigt.

Verfasst: Dienstag 4. Juli 2006, 08:04
von Steffen
Danke für die schnelle Hilfe, so funktionierts jetzt.
@alle, die ein ähnliches Problem haben: die time.Sleep() Anweisung steht für die Funktion, die man ausführen will während der Throbber läuft.
Gruß,
Steffen