Search code examples
python-3.xwxpythonwxwidgets

wxPython class doesnt show in window


So i created a class that runs a big calculation in a seperet thread.

This is what i expected to see:

Expected

And this is what i do see:

What i should see

This is the frame class

class ThreadFrame(wx.Frame):

def __init__(self,parent=None):
    wx.Frame.__init__(self,parent=parent)
    self.frame = wx.Frame(None, title='Bitte Warten',style=wx.FRAME_NO_TASKBAR)
    self.frame.SetSize(500,100)
    self.panel=wx.Panel(self.frame)
    self.parent=parent
    self.WaitLbl=wx.StaticText(self.panel,-1)
    self.WaitLbl.SetLabel('Geotags werden ausgelesen und abgerufen.')
    self.progress = wx.Gauge(self.panel,size=(500,30), range=self.parent.list_ctrl.GetItemCount())
    self.btn = wx.Button(self.panel,label='Abbrechen')
    self.btn.Bind(wx.EVT_BUTTON, self.OnExit)

    self.Sizer=wx.BoxSizer(wx.VERTICAL)          

    #Add Widgets LeftSizer
    self.Sizer.Add(self.WaitLbl,0,wx.ALL|wx.CENTER,5)
    self.Sizer.Add(self.progress,0,wx.ALL,5)
    self.Sizer.Add(self.btn,0,wx.ALL|wx.CENTER,5)


    self.panel.SetSizer(self.Sizer)
    self.Sizer.Fit(self.panel)
    self.panel.Layout()            
    self.Centre()            



    #Bind to the progress event issued by the thread
    self.Bind(EVT_PROGRESS_EVENT, self.OnProgress)
    #Bind to Exit on frame close
    #self.Bind(wx.EVT_CLOSE, self.OnExit)
    self.Show()

    self.mythread = TestThread(self.frame, self.parent)
    #Enable the GUI to be responsive by briefly returning control to the main App
    while self.mythread.isAlive():
        time.sleep(0.1)
        wx.GetApp().Yield()
        continue

    try:
        self.OnExit(None)
    except:
        pass

def OnProgress(self, event):
    self.progress.SetValue(event.count)
    #or for indeterminate progress
    #self.progress.Pulse()

def OnExit(self, event):
    if self.mythread.isAlive():
        print('Thread lebt noch')
        self.mythread.terminate() # Shutdown the thread
        print('Thread wird beendet')
        self.mythread.join() # Wait for it to finish

    self.Close()

And this is the thread where the calculation is running

class TestThread(Thread):
def __init__(self,parent_target,toplevel):
    Thread.__init__(self)
    self.parent = toplevel
    self.ownparent=parent_target
    self.stopthread = False
    self.start()    # start the thread

def run(self):
    print('Thread gestartet')
    i=0
    while self.stopthread == False:        
           #if calculation is not finished:
                #do calculation and count i one up
                evt = progress_event(count=i)

                    #Send back current count for the progress bar
                try:
                    wx.PostEvent(self.ownparent, evt)

                except: # The parent frame has probably been destroyed

                    self.terminate()
                i=i+1
        else:
            print('Thread Terminated')
            self.terminate()


def terminate(self):
    self.stopthread = True

And this is how i call the class from my main programm:

frame=ThreadFrame(self)

The main program also has a frame open. So this is a frame which is opend and then starts a thread which does calculation and then stops. I think thats all that is to know. I replaced the caluclation with speudo code because my brain hurts and i cant come up with a plachold right now. But i feel like between all the fiting and sizers and panels and frames i went somewhere wrong. And i totaly dont look through all of this stuff at the moment.


Solution

  • So im not sure what caused the problem. I started from scratch and now it works. This time i didnt use a new frame because the class itself is allready a frame.

    class GeoThreadFrame(wx.Frame):
    
    def __init__(self, radsteuer):
        wx.Frame.__init__(self,parent=radsteuer.frame,style=wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP|wx.FRAME_NO_TASKBAR)
        panel = wx.Panel(self)
        self.SetWindowStyle(wx.FRAME_NO_TASKBAR|wx.STAY_ON_TOP)
    
        self.progress = wx.Gauge(panel,size=(300,30), pos=(10,50), range=radsteuer.list_ctrl.GetItemCount())
    
        self.btn = wx.Button(panel,label='Abbrechen', size=(200,30), pos=(10,10))
        self.btn.Bind(wx.EVT_BUTTON, self.OnExit)
        panel.Center()
        #Bind to the progress event issued by the thread
        self.Bind(EVT_PROGRESS_EVENT, self.OnProgress)
        #Bind to Exit on frame close
        self.Bind(wx.EVT_CLOSE, self.OnExit)
        self.Center()
        self.Show()
    
        self.mythread = GeoLocationThread(self, radsteuer)
        #Enable the GUI to be responsive by briefly returning control to the main App
        while self.mythread.isAlive():            
            #time.sleep(0.1)
            wx.GetApp().Yield()
            continue
    
        try:
            self.OnExit(None)
        except:
            pass
    
    def OnProgress(self, event):
        self.progress.SetValue(event.count)
        #or for indeterminate progress
        #self.progress.Pulse()
    
    def OnExit(self, event):
    
        if self.mythread.isAlive():            
            self.mythread.terminate() # Shutdown the thread            
            #self.mythread.join(3) # Wait for it to finish            
        self.Destroy()
    
    class GeoLocationThread(Thread):
        def __init__(self,parent_target,mainparent):
            Thread.__init__(self)
            self.parent = parent_target
            self.mainparent=mainparent
            self.stopthread = False
            self.start()    # start the thread
    
        def run(self):
            # A loop that will run for 5 minutes then terminate
            i=0
            while self.stopthread == False:
    
    
                if i < self.mainparent.list_ctrl.GetItemCount():
                    self.calculation(i)
                    evt = progress_event(count=i)
                    i=i+1
                    #Send back current count for the progress bar
                    try:
                        wx.PostEvent(self.parent, evt)
                    except: # The parent frame has probably been destroyed
                        self.terminate()
                else:
                    self.terminate()
    
        def terminate(self):
    
            self.stopthread = True
    
        def calculate(self,i):
            #your calculation here