UltimateListCtrl - scroll problem

Hello

UltimateListCtrl with ULC_VIRTUAL sometimes does not display
all lines when scrolled vertically.
I can reproduce this with the sample below. When the scrollbar
is moved up and down, sometimes lines are missing (this error
does not occur immediately)

I debugged UltimateListCtrl and found out this:
- first UltimateListMainWindow handles wx.EVT_SCROLLWIN in OnScroll
- OnScroll sets _lineFrom to -1 (ResetVisibleLinesRange())
  (the value -1 means that _lineFrom should be recalculated)
- then UltimateListMainWindow handles wx.EVT_PAINT in OnPaint
- OnPaint calculates visibleFrom, visibleTo with
GetVisibleLinesRange()
  Because _lineFrom is -1, GetVisibleLinesRange sets _lineFrom
  to the value returned from GetScrollPos(wx.VERTICAL)
- The sequence above works correct as long as wx.EVT_PAINT
  follows wx.EVT_SCROLLWIN. But I found out that there a cases
  where 2 wx.EVT_SCROLLWIN events are received and then
  2 wx.EVT_PAINT events. This has the effect that in the
  handler for the second wx.EVT_PAINT event the value of _lineFrom
  is not -1 (because ResetVisibleLinesRange was not called).
  Instead _lineFrom still has the value from the first wx.EVT_PAINT
event,
  which is not the actual scroll-pos.

I do not know what is wrong here. Is it an error that wx.EVT_PAINT
does not follow every wx.EVT_SCROLLWIN or is the logic for caching
the scroll-pos in _lineFrom wrong or am I on the wrong path ?

I am using wxpython 2.8.12.1 and windows-vista.

Sample:

···

---
import wx
import wx.lib.agw.ultimatelistctrl as ulc

class ULCVirtual(ulc.UltimateListCtrl):
    def __init__(self, parent, style, agwstyle):
        agwstyle |= ulc.ULC_VIRTUAL
        ulc.UltimateListCtrl.__init__(self, parent, -1,
              style=style, agwStyle=agwstyle)

    def OnGetItemColumnKind(self, item, column=0):
        return 0

    def OnGetItemText(self, item, col):
        return "item {0}".format(item)

    def OnGetItemToolTip(self, item, col):
        return "item {0}".format(item)

    def OnGetItemTextColour(self, item, col):
        return wx.NullColour

    def OnGetItemColumnCheck(self, item, column=0):
        return False

    def OnGetItemAttr(self, item_idx):
        return ulc.UltimateListItemAttr()

class TestFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Test")
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        self.ulc = ULCVirtual(self,
            style=wx.NO_BORDER, agwstyle=ulc.ULC_REPORT)
        for i in range(2):
            self.ulc.InsertColumn(i, str(i))
        self.ulc.SetItemCount(1000)
        sizer.Add(self.ulc, 1, wx.EXPAND)

app = wx.PySimpleApp()
TestFrame().Show()
app.MainLoop()
---

Erwin

This bug still exists in 3.0…

I will pick up where Erwin left off, and hopefully file a ticket with a patch included. If I can’t fix it (hah! I hope I can fix it) I’ll make a ticket.

···

On Thursday, December 29, 2011 12:56:46 PM UTC-8, ErwinP wrote:

Hello

UltimateListCtrl with ULC_VIRTUAL sometimes does not display

all lines when scrolled vertically.

I can reproduce this with the sample below. When the scrollbar

is moved up and down, sometimes lines are missing (this error

does not occur immediately)

I debugged UltimateListCtrl and found out this:

  • first UltimateListMainWindow handles wx.EVT_SCROLLWIN in OnScroll

  • OnScroll sets _lineFrom to -1 (ResetVisibleLinesRange())

    (the value -1 means that _lineFrom should be recalculated)

  • then UltimateListMainWindow handles wx.EVT_PAINT in OnPaint

  • OnPaint calculates visibleFrom, visibleTo with

GetVisibleLinesRange()

Because _lineFrom is -1, GetVisibleLinesRange sets _lineFrom

to the value returned from GetScrollPos(wx.VERTICAL)

  • The sequence above works correct as long as wx.EVT_PAINT

    follows wx.EVT_SCROLLWIN. But I found out that there a cases

    where 2 wx.EVT_SCROLLWIN events are received and then

    2 wx.EVT_PAINT events. This has the effect that in the

    handler for the second wx.EVT_PAINT event the value of _lineFrom

    is not -1 (because ResetVisibleLinesRange was not called).

    Instead _lineFrom still has the value from the first wx.EVT_PAINT

event,

which is not the actual scroll-pos.

I do not know what is wrong here. Is it an error that wx.EVT_PAINT

does not follow every wx.EVT_SCROLLWIN or is the logic for caching

the scroll-pos in _lineFrom wrong or am I on the wrong path ?

I am using wxpython 2.8.12.1 and windows-vista.

Sample:


import wx

import wx.lib.agw.ultimatelistctrl as ulc

class ULCVirtual(ulc.UltimateListCtrl):

def __init__(self, parent, style, agwstyle):

    agwstyle |= ulc.ULC_VIRTUAL

    ulc.UltimateListCtrl.__init__(self, parent, -1,

          style=style, agwStyle=agwstyle)



def OnGetItemColumnKind(self, item, column=0):

    return 0



def OnGetItemText(self, item, col):

    return "item {0}".format(item)



def OnGetItemToolTip(self, item, col):

    return "item {0}".format(item)



def OnGetItemTextColour(self, item, col):

    return wx.NullColour



def OnGetItemColumnCheck(self, item, column=0):

    return False



def OnGetItemAttr(self, item_idx):

    return ulc.UltimateListItemAttr()

class TestFrame(wx.Frame):

def __init__(self):

    wx.Frame.__init__(self, None, -1, "Test")

    sizer = wx.BoxSizer(wx.VERTICAL)

    self.SetSizer(sizer)

    self.ulc = ULCVirtual(self,

        style=wx.NO_BORDER, agwstyle=ulc.ULC_REPORT)

    for i in range(2):

        self.ulc.InsertColumn(i, str(i))

    self.ulc.SetItemCount(1000)

    sizer.Add(self.ulc, 1, wx.EXPAND)

app = wx.PySimpleApp()

TestFrame().Show()

app.MainLoop()


Erwin