How to avoid wxPython ObjectListView going top when refreshing

69 views Asked by At

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()
0

There are 0 answers