我在使用 LC_VIRTUAL 时遇到 wx.ListCtrl 问题,无法找到正确的解决方法。
问题是如果 OnGetItemText() 花费太长时间来返回它的结果,控件的内容会闪烁。
到目前为止我尝试过的解决方案:
- SetDoubleBuffered - 如果在 ListCtrl 本身或父控件上完成,它会导致内容根本不显示
- 禁用背景擦除可修复闪烁,但会产生重绘问题,尤其是在调整控件大小时。
- Freeze() 和 Thaw() 没有任何效果,因为控件已经处于重绘的中间。
到目前为止,我想出的唯一解决方案是在调用 Refresh() 之前缓存新数据。但是,在某些情况下,我可能需要显示 100,000 条或更多记录,因此提前缓存它们是行不通的。
这是我构建的一个示例来演示该问题,尽管您可能必须根据 CPU 速度调整计数:
from __future__ import print_function, unicode_literals
import wx
class MyListCtrl ( wx.ListCtrl ):
def OnGetItemText ( self, item, column ):
ar = []
for i in range ( 200000 ):
ar.append ( i )
return '{}'.format ( len ( ar ) )
class MyFrame ( wx.Frame ):
lc = None
timer = None
def __init__ ( self, *args, **kwargs ):
super ( MyFrame, self ).__init__ ( *args, **kwargs )
self.timer = wx.Timer ( self )
self.lc = MyListCtrl ( self, style=wx.LC_VIRTUAL|wx.LC_REPORT )
self.lc.InsertColumn ( 0, 'Count1', width=75 )
self.lc.InsertColumn ( 1, 'Count2', width=75 )
self.lc.InsertColumn ( 2, 'Count3', width=75 )
self.lc.InsertColumn ( 3, 'Count4', width=75 )
self.lc.SetItemCount ( 1 )
self.Bind ( wx.EVT_TIMER, self.on_timer, self.timer )
self.Bind ( wx.EVT_CLOSE, self.on_close )
self.timer.Start ( 1000 )
def on_timer ( self, event ):
self.lc.Refresh()
def on_close ( self, event ):
self.timer.Stop()
event.Skip()
if __name__=='__main__':
app = wx.App ( False )
frame = MyFrame ( None )
frame.Show()
app.MainLoop()
我在两种工作环境中都遇到了这个问题:
Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import wx
>>> wx.version()
'3.0.2.0 msw (classic)'
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import wx
>>> wx.version()
'3.0.3.dev2680+55dda48 msw (phoenix)'