I've the example app below where there is this ObjectListView. My final app will have data periodically updated in an other thread and I'd like to refresh periodically the display. Thanks to Attila I managed to do so using timer events.
The problem is that when refreshing the ObjectListView with new data, the scroller goes on top of the list which makes possible to scroll down the list only between two refresh... As I intend to refresh several times per second, this is a problem !
Is there a way to refresh the object without changing the position of the scroller ?
Thanks Stephane
import wx
from ObjectListView import ObjectListView, ColumnDefn, BatchedUpdate
class MyFrame(wx.Frame):
def __init__(self, *args, **kw):
super(MyFrame, self).__init__(*args, **kw)
txt='0'
self.list = []
self.count = 0
# BoxSizers
pnl = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
hbox3 = wx.BoxSizer(wx.HORIZONTAL)
hbox4 = wx.BoxSizer(wx.HORIZONTAL)
# Widgets
self.gauge = wx.Gauge(pnl, range=50, size=(250, -1))
self.btn1 = wx.Button(pnl, wx.ID_OK)
self.btn2 = wx.Button(pnl, wx.ID_STOP)
self.text = wx.StaticText(pnl, label='Task to be done')
self.st1 = wx.StaticText(pnl, label=txt, style=wx.ALIGN_LEFT)
self.ListView = ObjectListView(pnl, wx.ID_ANY, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
self.ListView.SetColumns([
ColumnDefn("Count1", "left", 100, "count1"),
ColumnDefn("Count2", "right", 125, "count2", stringConverter="%.4f")])
font = wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.DEFAULT)
self.st1.SetFont(font)
# Bind buttons to functions
self.Bind(wx.EVT_BUTTON, self.OnOk, self.btn1)
self.Bind(wx.EVT_BUTTON, self.OnStop, self.btn2)
# Panel Layout
hbox1.Add(self.gauge, proportion=1, flag=wx.ALIGN_CENTRE)
hbox2.Add(self.btn1, proportion=1, flag=wx.RIGHT, border=10)
hbox2.Add(self.btn2, proportion=1)
hbox3.Add(self.text, proportion=1)
hbox4.Add(self.ListView, proportion=1)
vbox.Add((0, 30))
vbox.Add(hbox1, flag=wx.ALIGN_CENTRE)
vbox.Add((0, 20))
vbox.Add(hbox2, proportion=1, flag=wx.ALIGN_CENTRE)
vbox.Add(hbox3, proportion=1, flag=wx.ALIGN_CENTRE)
vbox.Add(hbox4, proportion=1, flag=wx.ALIGN_CENTRE)
vbox.Add(self.st1, flag=wx.ALL, border=15)
pnl.SetSizer(vbox)
self.SetTitle('wx.Gauge')
self.Centre()
# create a timer
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimerUpdate, self.timer)
self.SetDoubleBuffered(True)
def OnTimerUpdate(self, evt):
self.count = self.count + 1
# Update gauge value
self.gauge.SetValue(self.count)
# update Static Text widget value
txt = str(self.count)
self.st1.SetLabel(txt)
# Update ObjectListView widget
element={}
element['count1'] = self.count
element['count2'] = 50-self.count
self.list.append(element)
self.ListView.SetObjects(self.list)
if self.count == 50:
self.timer.Stop()
self.text.SetLabel('Task Completed')
def OnOk(self, e):
if self.count >= 50:
return
self.timer.Start(500)
self.text.SetLabel('Task in Progress')
def OnStop(self, e):
if self.count == 0 or self.count >= 50 or not self.timer.IsRunning():
return
self.timer.Stop()
self.text.SetLabel('Task Interrupted')
def main():
app = wx.App()
ex = MyFrame(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()