Scrollbar Detection in wxListCtrl

Hello,

I’m working on a project, and I wish to know if there is a way to ask the a wxListCtrl (or wxListView) if the scroll bars (horizontal and/or vertical) are being displayed or not.

OS: Fedora Core 6 and 7

wxPython: 2.6.3.2 and 2.8.4

Python: 2.5

I would like this to work cross platform but right now I’ll take any answer.

Tom

Pajak, Tom (GE Healthcare) wrote:

Hello,
I'm working on a project, and I wish to know if there is a way to ask the a wxListCtrl (or wxListView) if the scroll bars (horizontal and/or vertical) are being displayed or not.

No, although it could probably be guessed on wxGTK since it is using a wx.ScrolledWindow, but on wxMSW and optionally on wxMac a native widget is used and it doesn't give access to that info.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

It's a pretty terrible hack, but you can compare the rectangles from
GetClientRect(inside the scrollbars) with GetRect (outside the
scrollbars) and make an informed guess.

···

On 9/25/07, Pajak, Tom (GE Healthcare) <TomPajak@ge.com> wrote:

Hello,

I'm working on a project, and I wish to know if there is a way to ask the a
wxListCtrl (or wxListView) if the scroll bars (horizontal and/or vertical)
are being displayed or not.

OS: Fedora Core 6 and 7
wxPython: 2.6.3.2 and 2.8.4
Python: 2.5

I would like this to work cross platform but right now I'll take any answer.

Tom

Hello,

I thought that might be true.

So my next question is, how do we guess on wxGTK if the scroll bars are
up?

Also where can I put a request for a method in upcoming releases, that
would tell me this info ?

Tom

···

-----Original Message-----
From: Robin Dunn [mailto:robin@alldunn.com]
Sent: Tuesday, September 25, 2007 1:01 PM
To: wxPython-users@lists.wxwidgets.org
Subject: Re: [wxPython-users] Scrollbar Detection in wxListCtrl

Pajak, Tom (GE Healthcare) wrote:

Hello,

I'm working on a project, and I wish to know if there is a way to ask
the a wxListCtrl (or wxListView) if the scroll bars (horizontal and/or
vertical) are being displayed or not.

No, although it could probably be guessed on wxGTK since it is using a
wx.ScrolledWindow, but on wxMSW and optionally on wxMac a native widget
is used and it doesn't give access to that info.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

HasScrollbar() probably works for wxGtk. But why are you trying to
figure this out? Perhaps theres a better solution that looking for the
presence of scrollbars.

···

On 9/25/07, Pajak, Tom (GE Healthcare) <TomPajak@ge.com> wrote:

Hello,

I thought that might be true.

So my next question is, how do we guess on wxGTK if the scroll bars are
up?

Also where can I put a request for a method in upcoming releases, that
would tell me this info ?

Hello,

I had hoped HasScrollbar() would tell me if scroll bars were present,
but it is always returning False.

To the second part, I'm trying to put wxGauges on the wxListCtrl (report
mode) to track some progress for a given item. I have not been able to
find a sample solution to this so far, if there is any solutions or
places I could look any help would be great.

Until then I need to know when scroll bars are present, so that if I
draw the gauges myself can clip them if they run into a scroll bar.

Tom

···

-----Original Message-----
From: Chris Mellon [mailto:arkanes@gmail.com]
Sent: Tuesday, September 25, 2007 1:31 PM
To: wxPython-users@lists.wxwidgets.org
Subject: Re: [wxPython-users] Scrollbar Detection in wxListCtrl

On 9/25/07, Pajak, Tom (GE Healthcare) <TomPajak@ge.com> wrote:

Hello,

I thought that might be true.

So my next question is, how do we guess on wxGTK if the scroll bars
are up?

Also where can I put a request for a method in upcoming releases, that

would tell me this info ?

HasScrollbar() probably works for wxGtk. But why are you trying to
figure this out? Perhaps theres a better solution that looking for the
presence of scrollbars.

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

To the second part, I’m trying to put wxGauges on the wxListCtrl (report
mode) to track some progress for a given item. I have not been able to

find a sample solution to this so far, if there is any solutions or
places I could look any help would be great.

So all you need is a way to put a gauge in a listctrl?

See if that helps:

import sys
import wx

class TestList(wx.ListCtrl):
“”"
A List Ctrl with gauages
“”"
def init(self, parent, style = wx.LC_REPORT|wx.LC_VRULES|wx.CLIP_CHILDREN):
wx.ListCtrl.init(self, parent, wx.ID_ANY, style = style)
self.parent = parent

    # Progress bars
    self.progressBars = []
    self.clearBars = False
   
    # Columns

    self.InsertColumn(0, "Title")
    self.InsertColumn(1, "Progress")
    self.InsertColumn(2, "Details")
   
    self.SetColumnWidth(0, 200)
    self.SetColumnWidth(1, 100)
    self.SetColumnWidth(2, 200)

Some Items…

    index = self.InsertStringItem(sys.maxint, "The First Item")
    self.SetStringItem(index, 1, "0")
    self.SetStringItem(index, 2, "Nothing")

    index = self.InsertStringItem(sys.maxint, "The Second Item")
    self.SetStringItem(index, 1, "25")
    self.SetStringItem(index, 2, "its a start")
    index = self.InsertStringItem(sys.maxint, "The Third Item")
    self.SetStringItem(index, 1, "50")
    self.SetStringItem(index, 2, "Half way")
    index = self.InsertStringItem(

sys.maxint, “The Fourth Item”)
self.SetStringItem(index, 1, “75”)
self.SetStringItem(index, 2, “Almost…”)
index = self.InsertStringItem(sys.maxint, “The Last Item”)

    self.SetStringItem(index, 1, "100")
    self.SetStringItem(index, 2, "Complete")
   
    # Events
    self.Bind(wx.EVT_PAINT, self.OnPaint)
    self.Bind

(wx.EVT_LIST_COL_DRAGGING, self.OnPaint)
self.Bind(wx.EVT_LIST_COL_END_DRAG, self.OnPaint)
self.Bind(wx.EVT_SCROLL, self.OnPaint)

def OnPaint(self, event=None):
    """

    Handles the EVT_PAINT event
    """
    print "OnPaint"
    self._OnPaintBars()
    if event:
        event.Skip()
   
def _OnPaintBars(self):

    """
    Actual drawing of progress bars
    """
    # General list info
    rank = 1                            # the column with the gauges
    itemCount = self.GetItemCount()     # number of items
   
    # No progress column or no items
    if rank == -1 or not itemCount:
        [p.Destroy() for p in self.progressBars]
        del self.progressBars

[:]
return False

if self.clearBars:
self.clearBars = False
[p.Destroy() for p in self.progressBars]
del self.progressBars[:]

    # Indexes
    topItem = self.GetTopItem() # top
    visibleIndexes = range(topItem, topItem + min(self.GetCountPerPage()+1, itemCount)) # to show
   
    # Make sure no extra bars
    while len(self.progressBars) > itemCount:

        progressBar = self.progressBars.pop()
        progressBar.Destroy()

Make sure enough bars

    while len(self.progressBars) < itemCount:
        progressBar = self._getProgressBar()
        self.progressBars.append(progressBar)

Update bars positions, size and value

    rect = self.GetItemRect(topItem)
    size = (self.GetColumnWidth(rank)-4, rect[3]-4)
    x = rect[0] + sum([self.GetColumnWidth(i) for i in range(0, rank)]) + 2

    y = rect[1] + 2
    inc = rect[3]
   
    for row in range(itemCount):
        if row in visibleIndexes:
            bar = self.progressBars[row]
            if bar.GetPosition

() != (x, y):
if wx.Platform != “WXMSW”:
bar.Hide()
bar.SetPosition((x, y))
bar.SetSize(size)
bar.SetValue
(self.getItemValue(row, rank))
bar.Show()
y += inc
else:
self.progressBars[row].Hide()

return True

def _getProgressBar(self):
    return wx.Gauge(self, -1, style = wx.NO_BORDER)

def getItemValue(self, row, rank):
“”"
Just for testing, this method returns the value of an item
“”"
return row*25

class TestFrame(
wx.Frame):
def init(self):
wx.Frame.init(self, None, -1)
self.list = TestList(self)

if name == “main”:
app = wx.App(0)
f = TestFrame()
f.Show()
app.MainLoop()

  • Roee.
···

On 9/25/07, Pajak, Tom (GE Healthcare) TomPajak@ge.com wrote:

This is really close to what I’ve tried to implement, but I used OnInternalIdle.

Either way, if you run this program (under GTK) resize the frame so that the scroll bars appear, then make it small enough that the progress over write the scroll bars.

This is the problem I’m trying to solve. The progress bars will are drawn on top of the scroll bars, I need to detect when the scroll bars are shown so I can call wxSystemSetting_GetMetric() to get the scroll bar size and then clip the progress bars so that they do not over write the scroll bars.

Thanks, its nice to see I’m headed the right way.

Tom

···

From: roee shlomo [mailto:roee88@gmail.com]
Sent: Tuesday, September 25, 2007 4:50 PM
To:
wxPython-users@lists.wxwidgets.org
Subject: Re: [wxPython-users] Scrollbar Detection in wxListCtrl

On 9/25/07, Pajak, Tom (GE Healthcare) TomPajak@ge.com wrote:

To the second part, I’m trying to put wxGauges on the wxListCtrl (report
mode) to track some progress for a given item. I have not been able to
find a sample solution to this so far, if there is any solutions or
places I could look any help would be great.

So all you need is a way to put a gauge in a listctrl?

See if that helps:

import sys
import wx

class TestList(wx.ListCtrl):
“”"
A List Ctrl with gauages
“”"
def init(self, parent, style = wx.LC_REPORT|wx.LC_VRULES|wx.CLIP_CHILDREN):
wx.ListCtrl.init(self, parent, wx.ID_ANY, style = style)
self.parent = parent

      # Progress bars
      self.progressBars = []
      self.clearBars = False
     
      # Columns
      self.InsertColumn(0, "Title")
      self.InsertColumn(1, "Progress")
      self.InsertColumn(2, "Details")
     
      self.SetColumnWidth(0, 200)
      self.SetColumnWidth(1, 100)
      self.SetColumnWidth(2, 200)

Some Items…

      index = self.InsertStringItem(sys.maxint, "The First Item")
      self.SetStringItem(index, 1, "0")
      self.SetStringItem(index, 2, "Nothing")
      index = self.InsertStringItem(sys.maxint, "The Second Item")
      self.SetStringItem(index, 1, "25")
      self.SetStringItem(index, 2, "its a start")
      index = self.InsertStringItem(sys.maxint, "The Third Item")
      self.SetStringItem(index, 1, "50")
      self.SetStringItem(index, 2, "Half way")
      index = self.InsertStringItem( sys.maxint, "The Fourth Item")
      self.SetStringItem(index, 1, "75")
      self.SetStringItem(index, 2, "Almost...")
      index = self.InsertStringItem(sys.maxint, "The Last Item")
      self.SetStringItem(index, 1, "100")
      self.SetStringItem(index, 2, "Complete")
     
      # Events
      self.Bind(wx.EVT_PAINT, self.OnPaint)
      self.Bind (wx.EVT_LIST_COL_DRAGGING, self.OnPaint)
      self.Bind(wx.EVT_LIST_COL_END_DRAG, self.OnPaint)
      self.Bind(wx.EVT_SCROLL, self.OnPaint)
     
  def OnPaint(self, event=None):
      """
      Handles the EVT_PAINT event
      """
      print "OnPaint"
      self._OnPaintBars()
      if event:
          event.Skip()
     
  def _OnPaintBars(self):
      """
      Actual drawing of progress bars
      """
      # General list info
      rank = 1                            # the column with the gauges
      itemCount = self.GetItemCount()     # number of items
     
      # No progress column or no items
      if rank == -1 or not itemCount:
          [p.Destroy() for p in self.progressBars]
          del self.progressBars [:]
          return False

if self.clearBars:
self.clearBars = False
[p.Destroy() for p in self.progressBars]
del self.progressBars[:]

      # Indexes
      topItem = self.GetTopItem() # top
      visibleIndexes = range(topItem, topItem + min(self.GetCountPerPage()+1, itemCount)) # to show
     
      # Make sure no extra bars
      while len(self.progressBars) > itemCount:
          progressBar = self.progressBars.pop()
          progressBar.Destroy()

Make sure enough bars

      while len(self.progressBars) < itemCount:
          progressBar = self._getProgressBar()
          self.progressBars.append(progressBar)

Update bars positions, size and value

      rect = self.GetItemRect(topItem)
      size = (self.GetColumnWidth(rank)-4, rect[3]-4)
      x = rect[0] + sum([self.GetColumnWidth(i) for i in range(0, rank)]) + 2
      y = rect[1] + 2
      inc = rect[3]
     
      for row in range(itemCount):
          if row in visibleIndexes:
              bar = self.progressBars[row]
              if bar.GetPosition () != (x, y):
                  if wx.Platform != "__WXMSW__":
                      bar.Hide()
                  bar.SetPosition((x, y))
              bar.SetSize(size)
              bar.SetValue (self.getItemValue(row, rank))
              bar.Show()
              y += inc
          else:
              self.progressBars[row].Hide()

return True

  def _getProgressBar(self):
      return wx.Gauge(self, -1, style = wx.NO_BORDER)

def getItemValue(self, row, rank):
“”"
Just for testing, this method returns the value of an item
“”"
return row*25

class TestFrame( wx.Frame):
def init(self):
wx.Frame.init(self, None, -1)
self.list = TestList(self)

if name == “main”:
app = wx.App(0)
f = TestFrame()
f.Show()
app.MainLoop()

  • Roee.

Pajak, Tom (GE Healthcare) wrote:

This is really close to what I've tried to implement, but I used OnInternalIdle.
Either way, if you run this program (under GTK) resize the frame so that the scroll bars appear, then make it small enough that the progress over write the scroll bars.
This is the problem I'm trying to solve. The progress bars will are drawn on top of the scroll bars, I need to detect when the scroll bars are shown so I can call wxSystemSetting_GetMetric() to get the scroll bar size and then clip the progress bars so that they do not over write the scroll bars.
Thanks, its nice to see I'm headed the right way.

It probably overdraws the scrollbar because of the parentage of the gauges. On wxGTK the listctrl is actually composed of two windows, and if you are using the listctrl itself as the parent then the gauges end up being siblings with the scrolled portion of the listctrl, so they can overlap without the expected clipping. Try making the gauge parent be listctrl.GetMainWindow() instead and see if that helps.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Hello,

Thanks for everyones help, I finally got it (thanks esp. you Roee and Robin Dunn).

Below is Roees cood modified to work with Robins suggestion (Search for CHANGE):

···

import sys
import wx

class TestList(wx.ListCtrl):
“”"
A List Ctrl with gauages
“”"
def init(self, parent, style = wx.LC_REPORT|wx.LC_VRULES|wx.CLIP_CHILDREN):
wx.ListCtrl.init(self, parent, wx.ID_ANY, style = style)
self.parent = parent

    # Progress bars
    self.progressBars = []
    self.clearBars = False
   
    # Columns
    self.InsertColumn(0, "Title")
    self.InsertColumn(1, "Progress")
    self.InsertColumn(2, "Details")
   
    self.SetColumnWidth(0, 200)
    self.SetColumnWidth(1, 100)
    self.SetColumnWidth(2, 200)

    # Some Items...
    index = self.InsertStringItem(sys.maxint, "The First Item")
    self.SetStringItem(index, 1, "0")
    self.SetStringItem(index, 2, "Nothing")
    index = self.InsertStringItem(sys.maxint, "The Second Item")
    self.SetStringItem(index, 1, "25")
    self.SetStringItem(index, 2, "its a start")
    index = self.InsertStringItem(sys.maxint, "The Third Item")
    self.SetStringItem(index, 1, "50")
    self.SetStringItem(index, 2, "Half way")
    index = self.InsertStringItem( sys.maxint, "The Fourth Item")
    self.SetStringItem(index, 1, "75")
    self.SetStringItem(index, 2, "Almost...")
    index = self.InsertStringItem(sys.maxint, "The Last Item")
    self.SetStringItem(index, 1, "100")
    self.SetStringItem(index, 2, "Complete")
   
    # Events
    self.Bind(wx.EVT_PAINT, self.OnPaint)
    self.Bind (wx.EVT_LIST_COL_DRAGGING, self.OnPaint)
    self.Bind(wx.EVT_LIST_COL_END_DRAG, self.OnPaint)
    self.Bind(wx.EVT_SCROLL, self.OnPaint)
   
def OnPaint(self, event=None):
    """
    Handles the EVT_PAINT event
    """
    print "OnPaint"
    self._OnPaintBars()
    if event:
        event.Skip()
   
def _OnPaintBars(self):
    """
    Actual drawing of progress bars
    """
    # General list info
    rank = 1                            # the column with the gauges
    itemCount = self.GetItemCount()     # number of items
   
    # No progress column or no items
    if rank == -1 or not itemCount:
        [p.Destroy() for p in self.progressBars]
        del self.progressBars [:]
        return False

    if self.clearBars:
        self.clearBars = False
        [p.Destroy() for p in self.progressBars]
        del self.progressBars[:]
       
    # Indexes
    topItem = self.GetTopItem() # top
    visibleIndexes = range(topItem, topItem + min(self.GetCountPerPage()+1, itemCount)) # to show
   
    # Make sure no extra bars
    while len(self.progressBars) > itemCount:
        progressBar = self.progressBars.pop()
        progressBar.Destroy()

    # Make sure enough bars
    while len(self.progressBars) < itemCount:
        progressBar = self._getProgressBar()
        self.progressBars.append(progressBar)

    # Update bars positions, size and value
    rect = self.GetItemRect(topItem)
    size = (self.GetColumnWidth(rank)-4, rect[3]-4)
    x = rect[0] + sum([self.GetColumnWidth(i) for i in range(0, rank)]) + 2
    # CHANGE: start at 0 of main window, not at y = rect[1] + 2
    y = 0
    inc = rect[3]
   
    for row in range(itemCount):
        if row in visibleIndexes:
            bar = self.progressBars[row]
            if bar.GetPosition () != (x, y):
                if wx.Platform != "__WXMSW__":
                    bar.Hide()
                bar.SetPosition((x, y))
            bar.SetSize(size)
            bar.SetValue (self.getItemValue(row, rank))
            bar.Show()
            y += inc
        else:
            self.progressBars[row].Hide()

    return True

def _getProgressBar(self):
    # CHANGE: set parent to self.GetMainWindow() not self
    return wx.Gauge(self.GetMainWindow(), -1, style = wx.NO_BORDER)

def getItemValue(self, row, rank):
    """
    Just for testing, this method returns the value of an item
    """
    return row*25

class TestFrame( wx.Frame):
def init(self):
wx.Frame.init(self, None, -1)
self.list = TestList(self)

if name == “main”:
app = wx.App(0)
f = TestFrame()
f.Show()
app.MainLoop()


Tom Pajak


From: roee shlomo [mailto:roee88@gmail.com]
Sent: Tuesday, September 25, 2007 4:50 PM
To:
wxPython-users@lists.wxwidgets.org
Subject: Re: [wxPython-users] Scrollbar Detection in wxListCtrl

On 9/25/07, Pajak, Tom (GE Healthcare) TomPajak@ge.com wrote:

To the second part, I’m trying to put wxGauges on the wxListCtrl (report
mode) to track some progress for a given item. I have not been able to
find a sample solution to this so far, if there is any solutions or
places I could look any help would be great.

So all you need is a way to put a gauge in a listctrl?

See if that helps:

import sys
import wx

class TestList(wx.ListCtrl):
“”"
A List Ctrl with gauages
“”"
def init(self, parent, style = wx.LC_REPORT|wx.LC_VRULES|wx.CLIP_CHILDREN):
wx.ListCtrl.init(self, parent, wx.ID_ANY, style = style)
self.parent = parent

      # Progress bars
      self.progressBars = []
      self.clearBars = False
     
      # Columns
      self.InsertColumn(0, "Title")
      self.InsertColumn(1, "Progress")
      self.InsertColumn(2, "Details")
     
      self.SetColumnWidth(0, 200)
      self.SetColumnWidth(1, 100)
      self.SetColumnWidth(2, 200)

Some Items…

      index = self.InsertStringItem(sys.maxint, "The First Item")
      self.SetStringItem(index, 1, "0")
      self.SetStringItem(index, 2, "Nothing")
      index = self.InsertStringItem(sys.maxint, "The Second Item")
      self.SetStringItem(index, 1, "25")
      self.SetStringItem(index, 2, "its a start")
      index = self.InsertStringItem(sys.maxint, "The Third Item")
      self.SetStringItem(index, 1, "50")
      self.SetStringItem(index, 2, "Half way")
      index = self.InsertStringItem( sys.maxint, "The Fourth Item")
      self.SetStringItem(index, 1, "75")
      self.SetStringItem(index, 2, "Almost...")
      index = self.InsertStringItem(sys.maxint, "The Last Item")
      self.SetStringItem(index, 1, "100")
      self.SetStringItem(index, 2, "Complete")
     
      # Events
      self.Bind(wx.EVT_PAINT, self.OnPaint)
      self.Bind (wx.EVT_LIST_COL_DRAGGING, self.OnPaint)
      self.Bind(wx.EVT_LIST_COL_END_DRAG, self.OnPaint)
      self.Bind(wx.EVT_SCROLL, self.OnPaint)
     
  def OnPaint(self, event=None):
      """
      Handles the EVT_PAINT event
      """
      print "OnPaint"
      self._OnPaintBars()
      if event:
          event.Skip()
     
  def _OnPaintBars(self):
      """
      Actual drawing of progress bars
      """
      # General list info
      rank = 1                            # the column with the gauges
      itemCount = self.GetItemCount()     # number of items
     
      # No progress column or no items
      if rank == -1 or not itemCount:
          [p.Destroy() for p in self.progressBars]
          del self.progressBars [:]
          return False

if self.clearBars:
self.clearBars = False
[p.Destroy() for p in self.progressBars]
del self.progressBars[:]

      # Indexes
      topItem = self.GetTopItem() # top
      visibleIndexes = range(topItem, topItem + min(self.GetCountPerPage()+1, itemCount)) # to show
     
      # Make sure no extra bars
      while len(self.progressBars) > itemCount:
          progressBar = self.progressBars.pop()
          progressBar.Destroy()

Make sure enough bars

      while len(self.progressBars) < itemCount:
          progressBar = self._getProgressBar()
          self.progressBars.append(progressBar)

Update bars positions, size and value

      rect = self.GetItemRect(topItem)
      size = (self.GetColumnWidth(rank)-4, rect[3]-4)
      x = rect[0] + sum([self.GetColumnWidth(i) for i in range(0, rank)]) + 2
      y = rect[1] + 2
      inc = rect[3]
     
      for row in range(itemCount):
          if row in visibleIndexes:
              bar = self.progressBars[row]
              if bar.GetPosition () != (x, y):
                  if wx.Platform != "__WXMSW__":
                      bar.Hide()
                  bar.SetPosition((x, y))
              bar.SetSize(size)
              bar.SetValue (self.getItemValue(row, rank))
              bar.Show()
              y += inc
          else:
              self.progressBars[row].Hide()

return True

  def _getProgressBar(self):
      return wx.Gauge(self, -1, style = wx.NO_BORDER)

def getItemValue(self, row, rank):
“”"
Just for testing, this method returns the value of an item
“”"
return row*25

class TestFrame( wx.Frame):
def init(self):
wx.Frame.init(self, None, -1)
self.list = TestList(self)

if name == “main”:
app = wx.App(0)
f = TestFrame()
f.Show()
app.MainLoop()

  • Roee.

And here's a little hack to get a progress bar updated via a timer...

Rob

···

---

import sys
import wx

class TestList(wx.ListCtrl):
    """
    A List Ctrl with gauages
    """
    def __init__(self, parent, style =
wx.LC_REPORT|wx.LC_VRULES|wx.CLIP_CHILDREN):
        wx.ListCtrl.__init__(self, parent, wx.ID_ANY, style = style)
        self.parent = parent

        # Progress bars
        self.progressBars = []
        self.clearBars = False

        # Columns
        self.InsertColumn(0, "Title")
        self.InsertColumn(1, "Progress")
        self.InsertColumn(2, "Details")

        self.SetColumnWidth(0, 200)
        self.SetColumnWidth(1, 100)
        self.SetColumnWidth(2, 200)

        # Some Items...
        index = self.InsertStringItem(sys.maxint, "The First Item")
        self.SetStringItem(index, 1, "0")
        self.SetStringItem(index, 2, "Nothing")
        index = self.InsertStringItem(sys.maxint, "The Second Item")
        self.SetStringItem(index, 1, "25")
        self.SetStringItem(index, 2, "its a start")
        index = self.InsertStringItem(sys.maxint, "The Third Item")
        self.SetStringItem(index, 1, "50")
        self.SetStringItem(index, 2, "Half way")
        index = self.InsertStringItem( sys.maxint, "The Fourth Item")
        self.SetStringItem(index, 1, "75")
        self.SetStringItem(index, 2, "Almost...")
        index = self.InsertStringItem(sys.maxint, "The Last Item")
        self.SetStringItem(index, 1, "100")
        self.SetStringItem(index, 2, "Complete")

        index = self.InsertStringItem(sys.maxint, "Some progress...")
        self.SetStringItem(index, 1, "0")
        self.SetStringItem(index, 2, "Working")
        self.timeout = 200
        self.working_rank = 1 # column with the gauge
        self.working_index = index
        self.working_progress = 0
        self.timer = wx.PyTimer(self.OnNotify)
        self.timer.Start(self.timeout)

        self.visibleIndexes = []

        # Events
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind (wx.EVT_LIST_COL_DRAGGING, self.OnPaint)
        self.Bind(wx.EVT_LIST_COL_END_DRAG, self.OnPaint)
        self.Bind(wx.EVT_SCROLL, self.OnPaint)

    def OnNotify(self):
        self.working_progress += 1
        if self.working_progress > 100:
            self.working_progress = 0
        print self.working_progress

        row = self.working_index
        rank = self.working_rank
        self.SetStringItem(row, rank, str(self.working_progress))
        if row in self.visibleIndexes:
            bar = self.progressBars[row]
            print bar
            bar.SetValue(self.working_progress)
        self.timer.Start(self.timeout)

    def OnPaint(self, event=None):
        """
        Handles the EVT_PAINT event
        """
        print "OnPaint"
        self._OnPaintBars()
        if event:
            event.Skip()

    def _OnPaintBars(self):
        """
        Actual drawing of progress bars
        """
        # General list info
        rank = 1 # the column with the gauges
        itemCount = self.GetItemCount() # number of items

        # No progress column or no items
        if rank == -1 or not itemCount:
            [p.Destroy() for p in self.progressBars]
            del self.progressBars [:]
            return False

        if self.clearBars:
            self.clearBars = False
            [p.Destroy() for p in self.progressBars]
            del self.progressBars[:]

        # Indexes
        topItem = self.GetTopItem() # top
        self.visibleIndexes = range(topItem, topItem +
min(self.GetCountPerPage()+1, itemCount)) # to show

        # Make sure no extra bars
        while len(self.progressBars) > itemCount:
            progressBar = self.progressBars.pop()
            progressBar.Destroy()

        # Make sure enough bars
        while len(self.progressBars) < itemCount:
            progressBar = self._getProgressBar()
            self.progressBars.append(progressBar)

        # Update bars positions, size and value
        rect = self.GetItemRect(topItem)
        size = (self.GetColumnWidth(rank)-4, rect[3]-4)
        x = rect[0] + sum([self.GetColumnWidth(i) for i in range(0, rank)]) + 2

        # Compensate for differences when ListCtrl uses a native
        # scrolled list vs a scrolled window containing a list
        if self == self.GetMainWindow():
            y = rect[1] + 2
        else:
            y = 0

        inc = rect[3]

        for row in range(itemCount):
            if row in self.visibleIndexes:
                bar = self.progressBars[row]
                if bar.GetPosition () != (x, y):
                    if wx.Platform != "__WXMSW__":
                        bar.Hide()
                    bar.SetPosition((x, y))
                bar.SetSize(size)
                bar.SetValue(self.getItemValue(row, rank))
                bar.Show()
                y += inc
            else:
                self.progressBars[row].Hide()

        return True

    def _getProgressBar(self):
        return wx.Gauge(self.GetMainWindow(), -1, 100, style = wx.NO_BORDER)

    def getItemValue(self, row, rank):
        """
        Just for testing, this method returns the value of an item
        """
        if row == self.working_index:
            return self.working_progress
        return row*25

class TestFrame( wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1)
        self.list = TestList(self)

if __name__ == "__main__":
    app = wx.App(0)
    f = TestFrame()
    f.Show()
    app.MainLoop()