Question

I'm so troubled by this problem:

I've create a ListCtrl object, a TextCtrl object, and a button. First I fill some data into the ListCtrl object, when I press the button, it will append some strings into TextCtrl object and use SetStringItem to modify ListCtrl object.

As you can see in the button function, I've added time.sleep(2) in each loop. When I've got is when the button is pressed, TextCtrl will be refreshed every time the strings is inserted, but ListCtrl just freeze until the LOOP IS FINISHED, then it will display the correct strings.

I want to know how to refresh the ListCtrl object as soon as SetStringItem is called.

Any help is deeply appreciated.

Here is the code:

import wx                                                                                                       
import sys                                                                                      
import time                                                                                     

class Frame(wx.Frame):                                                                          
    def __init__(self, parent):                                                                 
        wx.Frame.__init__(self, parent, size=(450, 450))                                        
        self.panel = wx.Panel(self)                                                             
        self.dl = wx.ListCtrl(self,-1,size=(300,100),style=wx.LC_REPORT)                        

        self.dl.InsertColumn(0, 'File')                                                         
        self.dl.InsertColumn(1, 'Progress')                                                     
        self.dl.InsertColumn(2, 'State')                                                        

        for row in range(3):                                                                    
            labels = [l+str(row) for l in "FILE PERCENT STATE".split()]                         
            # sys.maxint inserts at the end of the list                                         
            index = self.dl.InsertStringItem(sys.maxint, labels[0])                             
            self.dl.SetStringItem(index, 1, labels[1])                                          
            self.dl.SetStringItem(index, 2, labels[2])                                          

        self.Show(True)                                                                         

        button2 = wx.Button(self, label=u"test", pos=(15, 200), size=(60, 25))                  
        self.Bind(wx.EVT_BUTTON, self.test, button2)                                            
        self.text = wx.TextCtrl(self, -1, pos=(80, 200), size=(200, 175), style=wx.TE_MULTILINE)
    def test(self,event):                                                                       
        for i in range(3):                                                                                                                                          
            self.dl.SetStringItem(i,1,"HELLO")                                                                                                            
            self.text.AppendText("HELLO")                                                       
            time.sleep(2)                                                                       

app = wx.App()                                                                                  
Frame(None)                                                                                     
app.MainLoop()                                                                                                                                        
Was it helpful?

Solution

The problem is that time.sleep blocks your GUI, what you will need to do to get the effect that you are trying for is:

On your button press add the first item & start a 2 second wx.Timer with an event handler/

In the event handler add the next string or if there are no more to add cancel the timer.

OTHER TIPS

I've changed my code to this, and it works, thanks steve

import wx
import sys
import time


class Frame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, size=(450, 450))
        self.panel = wx.Panel(self)
        self.dl = wx.ListCtrl(self,-1,size=(300,100),style=wx.LC_REPORT)

        self.dl.InsertColumn(0, 'File')
        self.dl.InsertColumn(1, 'Progress')
        self.dl.InsertColumn(2, 'State')

        for row in range(3):
            labels = [l+str(row) for l in "FILE PERCENT STATE".split()]
            # sys.maxint inserts at the end of the list
            index = self.dl.InsertStringItem(sys.maxint, labels[0])
            self.dl.SetStringItem(index, 1, labels[1])
            self.dl.SetStringItem(index, 2, labels[2])

        self.Show(True)

        self.timer = wx.Timer(self,-1)
        #self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.Bind(wx.EVT_TIMER, self.test1, self.timer)
        button2 = wx.Button(self, label=u"test", pos=(15, 200), size=(60, 25))
        self.Bind(wx.EVT_BUTTON, self.test, button2)
        self.text = wx.TextCtrl(self, -1, pos=(80, 200), size=(200, 175), style=wx.TE_MULTILINE)
        self.z=0



    def test(self,event):
        self.timer.Start(3000)

    def test1(self,event):
        for i in range(1):
            self.dl.SetStringItem(self.z,1,"HELLO")
            self.text.AppendText("HELLO")
            self.z+=1           
            if self.z >2 :
               self.timer.Stop()  


app = wx.App()
Frame(None)
app.MainLoop()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top