New gizmos.TreeListCtrl much slower than 2.8 version
Operating system: LIN64 / WIN64 wxPython version & source: 2.8 / 4.1.1 Python version & source: 2.7 / 3.8
Description of the problem:
The new version of the TreeListCtrl (only a compatibility wrapper based on hypertreelist) is much slower, if it gets big (1000 entries +). With slow I mean it takes long to be filled and is very laggy at scrolling, opening subchilds, ...
I tested the hypertreelist in wxpython2.8 and it's the same behavior. Only the TreeListCtrl is fast at 2.8
Please see example below. You can switch between hypertreelist / treelistctrl in the main It runs with 2.8 / 4.1.1
Thank you for your work and best regards Roland
Code Example (click to expand)
import wx
import wx.lib.agw.hypertreelist as hypertreelist
import wx.gizmos as gizmos
import random
class MyFrame(wx.Frame):
def __init__(self, tree_type):
wx.Frame.__init__(self, None, wx.ID_ANY)
if wx.version().startswith("4"):
if tree_type.startswith("hyper"):
tree = hypertreelist.HyperTreeList(self, -1, style=0, agwStyle=hypertreelist.TR_DEFAULT_STYLE | hypertreelist.TR_HIDE_ROOT |
hypertreelist.TR_FULL_ROW_HIGHLIGHT | hypertreelist.TR_ROW_LINES |
hypertreelist.TR_COLUMN_LINES)
else:
tree = gizmos.TreeListCtrl(self, -1, style=0, agwStyle=gizmos.TR_DEFAULT_STYLE | gizmos.TR_HIDE_ROOT | gizmos.TR_FULL_ROW_HIGHLIGHT |
gizmos.TR_ROW_LINES | gizmos.TR_COLUMN_LINES)
else:
if tree_type.startswith("hyper"):
tree = hypertreelist.HyperTreeList(self, -1, style=0, agwStyle=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT |
wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_ROW_LINES |
wx.TR_HAS_VARIABLE_ROW_HEIGHT | wx.TR_NO_LINES |
wx.TR_COLUMN_LINES)
else:
tree = gizmos.TreeListCtrl(self, -1, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.TR_FULL_ROW_HIGHLIGHT |
wx.TR_ROW_LINES | wx.TR_COLUMN_LINES)
col_count = 10
for i in range(col_count):
tree.AddColumn("Column "+str(i))
tree.SetMainColumn(0)
root = tree.AddRoot("The root item")
for i in range(2):
child = tree.AppendItem(root, "platform "+str(i))
for i in range(5000):
child_child = tree.AppendItem(child, "job "+str(i))
for col in range(col_count):
tree.SetItemText(child_child, str(random.randrange(10)), col+1)
for i in range(2):
tree.AppendItem(child_child, "diff "+str(i))
if __name__ == '__main__':
app = wx.App(False)
#mainwin = MyFrame("hyper")
mainwin = MyFrame("gizmos")
mainwin.Show(True)
mainwin.SetSize((1100, 800))
app.MainLoop()
I spent some time profiling the hypertreelist and I think that there are several things which could be done more efficiency.
1. Initial opening of the example:
- if i remove the self.CalculateSize(item, dc)@4139 the opening time is reduced from about 20sec to 2secs
- I think he calculates the size of all element even if they are not drawn
2. Opening/closing the first level a few times:
- snakeviz shows, that the time is also spent in CalculateSize again
- and in this Function the time is mostly spent in GetFullMultiLineTextExtent
Profile Output (click to expand)
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3962 @profile
3963 def CalculateSize(self, item, dc):
3964 """
3965 Calculates overall position and size of an item.
3966
3967 :param `item`: an instance of :class:`TreeListItem`;
3968 :param `dc`: an instance of :class:`wx.DC`.
3969 """
3970 20016 22433.0 1.1 0.4 if item.IsHidden():
3971 # Hidden items have a height of 0.
3972 item.SetHeight(0)
3973 return
3974
3975 20016 19459.0 1.0 0.4 attr = item.GetAttributes()
3976
3977 20016 11314.0 0.6 0.2 if attr and attr.HasFont():
3978 dc.SetFont(attr.GetFont())
3979 20016 20974.0 1.0 0.4 elif item.IsBold():
3980 dc.SetFont(self._boldFont)
3981 else:
3982 20016 38255.0 1.9 0.8 dc.SetFont(self._normalFont)
3983
3984 20016 13785.0 0.7 0.3 text_w = text_h = wnd_w = wnd_h = 0
3985 220176 158835.0 0.7 3.1 for column in range(self.GetColumnCount()):
3986 200160 3269190.0 16.3 64.2 w, h, dummy = dc.GetFullMultiLineTextExtent(item.GetText(column))
3987 200160 280539.0 1.4 5.5 text_w, text_h = max(w, text_w), max(h, text_h)
3988
3989 200160 368483.0 1.8 7.2 wnd = item.GetWindow(column)
3990 200160 116273.0 0.6 2.3 if wnd:
3991 wnd_h = max(wnd_h, item.GetWindowSize(column)[1])
3992 if column == self._main_column:
3993 wnd_w = item.GetWindowSize(column)[0]
3994
3995 20016 392498.0 19.6 7.7 text_w, dummy, dummy = dc.GetFullMultiLineTextExtent(item.GetText(self._main_column))
3996 20016 20624.0 1.0 0.4 text_h+=2
3997
3998 # restore normal font
3999 20016 54587.0 2.7 1.1 dc.SetFont(self._normalFont)
4000
4001 20016 13009.0 0.6 0.3 image_w, image_h = 0, 0
4002 20016 114204.0 5.7 2.2 image = item.GetCurrentImage()
4003
4004 20016 14265.0 0.7 0.3 if image != _NO_IMAGE:
4005
4006 if self._imageListNormal:
4007
4008 image_w, image_h = self._imageListNormal.GetSize(image)
4009 image_w += 2*_MARGIN
4010
4011 20016 14806.0 0.7 0.3 total_h = ((image_h > text_h) and [image_h] or [text_h])[0]
4012
4013 20016 25661.0 1.3 0.5 checkimage = item.GetCurrentCheckedImage()
4014 20016 12786.0 0.6 0.3 if checkimage is not None:
4015 wcheck, hcheck = self._imageListCheck.GetSize(0)
4016 wcheck += 2*_MARGIN
4017 else:
4018 20016 11841.0 0.6 0.2 wcheck = 0
4019
4020 20016 12239.0 0.6 0.2 if total_h < 30:
4021 20016 12932.0 0.6 0.3 total_h += 2 # at least 2 pixels
4022 else:
4023 total_h += total_h//10 # otherwise 10% extra spacing
4024
4025 20016 13421.0 0.7 0.3 if total_h > self._lineHeight:
4026 1 2.0 2.0 0.0 self._lineHeight = max(total_h, wnd_h+2)
4027
4028 20016 32772.0 1.6 0.6 item.SetWidth(image_w+text_w+wcheck+2+wnd_w)
4029 20016 29772.0 1.5 0.6 item.SetHeight(max(total_h, wnd_h+2))
3. Scrolling around a little:
- here hypertreelist.py:2850(PaintItem) is dominant
Profile Output (click to expand)
File: /usr/local/lib/python3.8/dist-packages/wx/lib/agw/hypertreelist.py
Function: PaintItem at line 2849
Line # Hits Time Per Hit % Time Line Contents
==============================================================
2849 @profile
2850 def PaintItem(self, item, dc):
2851 """
2852 Actually draws an item.
2853
2854 :param `item`: an instance of :class:`TreeListItem`;
2855 :param `dc`: an instance of :class:`wx.DC`.
2856 """
2857
2858 7001 18431.0 2.6 0.1 def _paintText(text, textrect, alignment):
2859 """
2860 Sub-function to draw multi-lines text label aligned correctly.
2861
2862 :param `text`: the item text label (possibly multiline);
2863 :param `textrect`: the label client rectangle;
2864 :param `alignment`: the alignment for the text label, one of ``wx.ALIGN_LEFT``,
2865 ``wx.ALIGN_RIGHT``, ``wx.ALIGN_CENTER``.
2866 """
2867
2868 txt = text.splitlines()
2869 if alignment != wx.ALIGN_LEFT and len(txt):
2870 yorigin = textrect.Y
2871 for t in txt:
2872 w, h = dc.GetTextExtent(t)
2873 plus = textrect.Width - w
2874 if alignment == wx.ALIGN_CENTER:
2875 plus //= 2
2876 dc.DrawLabel(t, wx.Rect(textrect.X + plus, yorigin, w, yorigin+h))
2877 yorigin += h
2878 return
2879 dc.DrawLabel(text, textrect)
2880
2881 7001 18365.0 2.6 0.1 attr = item.GetAttributes()
2882
2883 7001 11909.0 1.7 0.1 if attr and attr.HasFont():
2884 dc.SetFont(attr.GetFont())
2885 7001 16332.0 2.3 0.1 elif item.IsBold():
2886 dc.SetFont(self._boldFont)
2887 7001 14701.0 2.1 0.1 if item.IsHyperText():
2888 dc.SetFont(self.GetHyperTextFont())
2889 if item.GetVisited():
2890 dc.SetTextForeground(self.GetHyperTextVisitedColour())
2891 else:
2892 dc.SetTextForeground(self.GetHyperTextNewColour())
2893
2894 7001 130109.0 18.6 0.7 colText = wx.Colour(*dc.GetTextForeground())
2895
2896 7001 17903.0 2.6 0.1 if item.IsSelected():
2897 colTextHilight = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
2898
2899 else:
2900 7001 14465.0 2.1 0.1 attr = item.GetAttributes()
2901 7001 11622.0 1.7 0.1 if attr and attr.HasTextColour():
2902 colText = attr.GetTextColour()
2903
2904 7001 12483.0 1.8 0.1 if self._vistaselection:
2905 colText = colTextHilight = wx.BLACK
2906
2907 7001 24101.0 3.4 0.1 total_w = self._owner.GetHeaderWindow().GetWidth()
2908 7001 22933.0 3.3 0.1 total_h = self.GetLineHeight(item)
2909 7001 19800.0 2.8 0.1 off_h = (self.HasAGWFlag(TR_ROW_LINES) and [1] or [0])[0]
2910 7001 15741.0 2.2 0.1 off_w = (self.HasAGWFlag(TR_COLUMN_LINES) and [1] or [0])[0]
2911 ## clipper = wx.DCClipper(dc, 0, item.GetY(), total_w, total_h) # only within line
2912
2913 7001 272515.0 38.9 1.5 text_w, text_h, dummy = dc.GetFullMultiLineTextExtent(item.GetText(self.GetMainColumn()))
2914
2915 7001 15489.0 2.2 0.1 drawItemBackground = False
2916 # determine background and show it
2917 7001 12342.0 1.8 0.1 if attr and attr.HasBackgroundColour():
2918 colBg = attr.GetBackgroundColour()
2919 drawItemBackground = True
2920 else:
2921 7001 12998.0 1.9 0.1 colBg = self._backgroundColour
2922
2923 7001 59361.0 8.5 0.3 dc.SetBrush(wx.Brush(colBg))
2924 7001 12133.0 1.7 0.1 if attr and attr.HasBorderColour():
2925 colBorder = attr.GetBorderColour()
2926 dc.SetPen(wx.Pen(colBorder, 1))
2927 else:
2928 7001 20446.0 2.9 0.1 dc.SetPen(wx.TRANSPARENT_PEN)
2929
2930 7001 21436.0 3.1 0.1 if self.HasAGWFlag(wx.TR_FULL_ROW_HIGHLIGHT):
2931
2932 7001 29993.0 4.3 0.2 itemrect = wx.Rect(0, item.GetY() + off_h, total_w-1, total_h - off_h)
2933
2934 7001 13505.0 1.9 0.1 if item == self._dragItem:
2935 dc.SetBrush(self._hilightBrush)
2936 if wx.Platform == "__WXMAC__":
2937 dc.SetPen((item == self._dragItem) and [wx.BLACK_PEN] or [wx.TRANSPARENT_PEN])[0]
2938
2939 dc.SetTextForeground(colTextHilight)
2940
2941 7001 15666.0 2.2 0.1 elif item.IsSelected():
2942
2943 wnd = item.GetWindow(self._main_column)
2944 wndx = 0
2945 if wnd:
2946 wndx, wndy = item.GetWindowSize(self._main_column)
2947
2948 itemrect = wx.Rect(0, item.GetY() + off_h, total_w-1, total_h - off_h)
2949
2950 if self._usegradients:
2951 if self._gradientstyle == 0: # Horizontal
2952 self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
2953 else: # Vertical
2954 self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
2955 elif self._vistaselection:
2956 self.DrawVistaRectangle(dc, itemrect, self._hasFocus)
2957 else:
2958 if wx.Platform in ["__WXGTK2__", "__WXMAC__"]:
2959 flags = wx.CONTROL_SELECTED
2960 if self._hasFocus: flags = flags | wx.CONTROL_FOCUSED
2961 wx.RendererNative.Get().DrawItemSelectionRect(self._owner, dc, itemrect, flags)
2962 else:
2963 dc.SetBrush((self._hasFocus and [self._hilightBrush] or [self._hilightUnfocusedBrush])[0])
2964 dc.SetPen((self._hasFocus and [self._borderPen] or [wx.TRANSPARENT_PEN])[0])
2965 dc.DrawRectangle(itemrect)
2966
2967 dc.SetTextForeground(colTextHilight)
2968
2969 # On GTK+ 2, drawing a 'normal' background is wrong for themes that
2970 # don't allow backgrounds to be customized. Not drawing the background,
2971 # except for custom item backgrounds, works for both kinds of theme.
2972 7001 11844.0 1.7 0.1 elif drawItemBackground:
2973
2974 itemrect = wx.Rect(0, item.GetY() + off_h, total_w-1, total_h - off_h)
2975 dc.SetBrush(wx.Brush(colBg, wx.SOLID))
2976 dc.DrawRectangle(itemrect)
2977 dc.SetTextForeground(colText)
2978
2979 else:
2980 7001 25767.0 3.7 0.1 dc.SetTextForeground(colText)
2981
2982 else:
2983
2984 dc.SetTextForeground(colText)
2985
2986 7001 16688.0 2.4 0.1 text_extraH = (total_h > text_h and [(total_h - text_h)//2] or [0])[0]
2987 7001 13927.0 2.0 0.1 img_extraH = (total_h > self._imgHeight and [(total_h-self._imgHeight)//2] or [0])[0]
2988 7001 11761.0 1.7 0.1 x_colstart = 0
2989
2990 77011 163212.0 2.1 0.9 for i in range(self.GetColumnCount()):
2991 70010 363623.0 5.2 2.0 if not self._owner.GetHeaderWindow().IsColumnShown(i):
2992 continue
2993
2994 70010 235350.0 3.4 1.3 col_w = self._owner.GetHeaderWindow().GetColumnWidth(i)
2995 70010 442336.0 6.3 2.4 dc.SetClippingRegion(x_colstart, item.GetY(), col_w, total_h) # only within column
2996
2997 70010 126313.0 1.8 0.7 image = _NO_IMAGE
2998 70010 125881.0 1.8 0.7 x = image_w = wcheck = hcheck = 0
2999
3000 70010 151818.0 2.2 0.8 if i == self.GetMainColumn():
3001 7001 15631.0 2.2 0.1 x = item.GetX() + _MARGIN
3002 7001 20233.0 2.9 0.1 if self.HasButtons():
3003 7001 14297.0 2.0 0.1 x += (self._btnWidth-self._btnWidth2) + _LINEATROOT
3004 else:
3005 x -= self._indent//2
3006
3007 7001 12086.0 1.7 0.1 if self._imageListNormal:
3008 image = item.GetCurrentImage(i)
3009
3010 7001 15206.0 2.2 0.1 if item.GetType() != 0 and self._imageListCheck:
3011 checkimage = item.GetCurrentCheckedImage()
3012 wcheck, hcheck = self._imageListCheck.GetSize(item.GetType())
3013 else:
3014 7001 12416.0 1.8 0.1 wcheck, hcheck = 0, 0
3015
3016 else:
3017 63009 114645.0 1.8 0.6 x = x_colstart + _MARGIN
3018 63009 242058.0 3.8 1.3 image = item.GetImage(column=i)
3019
3020 70010 120726.0 1.7 0.7 if image != _NO_IMAGE:
3021 image_w = self._imgWidth + _MARGIN
3022
3023 # honor text alignment
3024 70010 300780.0 4.3 1.7 text = item.GetText(i)
3025 70010 248684.0 3.6 1.4 alignment = self._owner.GetHeaderWindow().GetColumn(i).GetAlignment()
3026
3027 70010 1523644.0 21.8 8.4 text_w, dummy, dummy = dc.GetFullMultiLineTextExtent(text)
3028
3029 70010 164777.0 2.4 0.9 if alignment == wx.ALIGN_RIGHT:
3030 w = col_w - (image_w + wcheck + text_w + off_w + _MARGIN + 1)
3031 x += (w > 0 and [w] or [0])[0]
3032
3033 70010 123745.0 1.8 0.7 elif alignment == wx.ALIGN_CENTER:
3034 w = (col_w - (image_w + wcheck + text_w + off_w + _MARGIN))//2
3035 x += (w > 0 and [w] or [0])[0]
3036 else:
3037 70010 126904.0 1.8 0.7 if image_w == 0 and wcheck:
3038 x += 2*_MARGIN
3039
3040 70010 132645.0 1.9 0.7 text_x = x + image_w + wcheck + 1
3041
3042 70010 161703.0 2.3 0.9 if i == self.GetMainColumn():
3043 7001 17174.0 2.5 0.1 item.SetTextX(text_x)
3044
3045 70010 193593.0 2.8 1.1 if not self.HasAGWFlag(wx.TR_FULL_ROW_HIGHLIGHT):
3046 dc.SetBrush((self._hasFocus and [self._hilightBrush] or [self._hilightUnfocusedBrush])[0])
3047 dc.SetPen((self._hasFocus and [self._borderPen] or [wx.TRANSPARENT_PEN])[0])
3048 if i == self.GetMainColumn():
3049 if item == self._dragItem:
3050 if wx.Platform == "__WXMAC__": # don't draw rect outline if we already have the background colour
3051 dc.SetPen((item == self._dragItem and [wx.BLACK_PEN] or [wx.TRANSPARENT_PEN])[0])
3052
3053 dc.SetTextForeground(colTextHilight)
3054
3055 elif item.IsSelected():
3056
3057 itemrect = wx.Rect(text_x-2, item.GetY() + off_h, text_w+2*_MARGIN, total_h - off_h)
3058
3059 if self._usegradients:
3060 if self._gradientstyle == 0: # Horizontal
3061 self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
3062 else: # Vertical
3063 self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
3064 elif self._vistaselection:
3065 self.DrawVistaRectangle(dc, itemrect, self._hasFocus)
3066 else:
3067 if wx.Platform in ["__WXGTK2__", "__WXMAC__"]:
3068 flags = wx.CONTROL_SELECTED
3069 if self._hasFocus: flags = flags | wx.CONTROL_FOCUSED
3070 wx.RendererNative.Get().DrawItemSelectionRect(self._owner, dc, itemrect, flags)
3071 else:
3072 dc.DrawRectangle(itemrect)
3073
3074 dc.SetTextForeground(colTextHilight)
3075
3076 elif item == self._current:
3077 dc.SetPen((self._hasFocus and [wx.BLACK_PEN] or [wx.TRANSPARENT_PEN])[0])
3078
3079 # On GTK+ 2, drawing a 'normal' background is wrong for themes that
3080 # don't allow backgrounds to be customized. Not drawing the background,
3081 # except for custom item backgrounds, works for both kinds of theme.
3082 elif drawItemBackground:
3083
3084 if self.HasAGWFlag(TR_FILL_WHOLE_COLUMN_BACKGROUND):
3085 itemrect = wx.Rect(text_x-2, item.GetY() + off_h, col_w-2*_MARGIN, total_h - off_h)
3086 else:
3087 itemrect = wx.Rect(text_x-2, item.GetY() + off_h, text_w+2*_MARGIN, total_h - off_h)
3088 dc.SetBrush(wx.Brush(colBg))
3089 dc.SetPen(wx.TRANSPARENT_PEN)
3090 dc.DrawRectangle(itemrect)
3091
3092 else:
3093 dc.SetTextForeground(colText)
3094
3095 else:
3096
3097 if self.HasAGWFlag(TR_FILL_WHOLE_COLUMN_BACKGROUND):
3098 itemrect = wx.Rect(text_x-2, item.GetY() + off_h, col_w-2*_MARGIN, total_h - off_h)
3099 else:
3100 itemrect = wx.Rect(text_x-2, item.GetY() + off_h, text_w+2*_MARGIN, total_h - off_h)
3101 colBgX = item.GetBackgroundColour(i)
3102
3103 if colBgX is not None and i != 0:
3104 dc.SetBrush(wx.Brush(colBgX, wx.SOLID))
3105 dc.SetPen(wx.TRANSPARENT_PEN)
3106 dc.DrawRectangle(itemrect)
3107
3108 dc.SetTextForeground(colText)
3109
3110 else:
3111
3112 70010 162127.0 2.3 0.9 if not item.IsSelected():
3113
3114 70010 154208.0 2.2 0.9 if self.HasAGWFlag(TR_FILL_WHOLE_COLUMN_BACKGROUND):
3115 itemrect = wx.Rect(text_x-2, item.GetY() + off_h, col_w-2*_MARGIN, total_h - off_h)
3116 else:
3117 70010 419543.0 6.0 2.3 itemrect = wx.Rect(text_x-2, item.GetY() + off_h, text_w+2*_MARGIN, total_h - off_h)
3118 70010 194377.0 2.8 1.1 colBgX = item.GetBackgroundColour(i)
3119
3120 70010 125333.0 1.8 0.7 if colBgX is not None:
3121 dc.SetBrush(wx.Brush(colBgX, wx.SOLID))
3122 dc.SetPen(wx.TRANSPARENT_PEN)
3123 dc.DrawRectangle(itemrect)
3124
3125
3126 70010 160851.0 2.3 0.9 if self.HasAGWFlag(TR_COLUMN_LINES): # vertical lines between columns
3127 70010 802545.0 11.5 4.4 pen = wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT), 1, wx.PENSTYLE_SOLID)
3128 70010 669559.0 9.6 3.7 dc.SetPen((self.GetBackgroundColour() == wx.WHITE and [pen] or [wx.WHITE_PEN])[0])
3129 70010 1111372.0 15.9 6.2 dc.DrawLine(x_colstart+col_w-1, item.GetY(), x_colstart+col_w-1, item.GetY()+total_h)
3130
3131 70010 208158.0 3.0 1.2 dc.SetBackgroundMode(wx.TRANSPARENT)
3132
3133 70010 132053.0 1.9 0.7 if image != _NO_IMAGE:
3134 y = item.GetY() + img_extraH
3135 if wcheck:
3136 x += wcheck
3137
3138 if item.IsEnabled():
3139 imglist = self._imageListNormal
3140 else:
3141 imglist = self._grayedImageList
3142
3143 imglist.Draw(image, dc, x, y, wx.IMAGELIST_DRAW_TRANSPARENT)
3144
3145 70010 125815.0 1.8 0.7 if wcheck:
3146 if item.IsEnabled():
3147 imglist = self._imageListCheck
3148 else:
3149 imglist = self._grayedCheckList
3150
3151 if self.HasButtons(): # should the item show a button?
3152 btnWidth = self._btnWidth
3153 else:
3154 btnWidth = -self._btnWidth
3155
3156 imglist.Draw(checkimage, dc,
3157 item.GetX() + btnWidth + _MARGIN,
3158 item.GetY() + ((total_h > hcheck) and [(total_h-hcheck)//2] or [0])[0]+1,
3159 wx.IMAGELIST_DRAW_TRANSPARENT)
3160
3161 70010 1675573.0 23.9 9.3 text_w, text_h, dummy = dc.GetFullMultiLineTextExtent(text)
3162 70010 214839.0 3.1 1.2 text_extraH = (total_h > text_h and [(total_h - text_h)//2] or [0])[0]
3163 70010 194635.0 2.8 1.1 text_y = item.GetY() + text_extraH
3164 70010 356173.0 5.1 2.0 textrect = wx.Rect(text_x, text_y, text_w, text_h)
3165
3166 70010 197033.0 2.8 1.1 if self.HasAGWFlag(TR_ELLIPSIZE_LONG_ITEMS):
3167 if i == self.GetMainColumn():
3168 maxsize = col_w - text_x - _MARGIN
3169 else:
3170 maxsize = col_w - (wcheck + image_w + _MARGIN)
3171
3172 text = ChopText(dc, text, maxsize)
3173
3174 70010 193795.0 2.8 1.1 if not item.IsEnabled():
3175 foreground = dc.GetTextForeground()
3176 dc.SetTextForeground(self._disabledColour)
3177 _paintText(text, textrect, alignment)
3178 dc.SetTextForeground(foreground)
3179 else:
3180 70010 145029.0 2.1 0.8 if ( wx.Platform == "__WXMAC__" and item.IsSelected() and
3181 self._hasFocus and i == self.GetMainColumn()) :
3182 # Use white on Macs, but only on the primary column if
3183 # TR_FULL_ROW_HIGHLIGHT is NOT turned on.
3184 dc.SetTextForeground(wx.WHITE)
3185 70010 3389633.0 48.4 18.8 _paintText(text, textrect, alignment)
3186
3187 70010 303569.0 4.3 1.7 wnd = item.GetWindow(i)
3188 70010 127941.0 1.8 0.7 if wnd:
3189 if text_w == 0:
3190 wndx = text_x
3191 else:
3192 wndx = text_x + text_w + 2*_MARGIN
3193 xa, ya = self.CalcScrolledPosition(0, item.GetY())
3194 wndx += xa
3195 if item.GetHeight() > item.GetWindowSize(i)[1]:
3196 ya += (item.GetHeight() - item.GetWindowSize(i)[1])//2
3197
3198 if wnd.GetPosition() != (wndx, ya):
3199 wnd.Move(wndx, ya, flags=wx.SIZE_ALLOW_MINUS_ONE)
3200 # Force window visible after any position changes were made.
3201 if not wnd.IsShown():
3202 wnd.Show()
3203
3204 70010 136071.0 1.9 0.8 x_colstart += col_w
3205 70010 759258.0 10.8 4.2 dc.DestroyClippingRegion()
3206
3207 # restore normal font
3208 7001 27260.0 3.9 0.2 dc.SetFont(self._normalFont)
Hope this helps a little bit. I think there is some optimizaion potential like not always asking the sizes and set pens ... But it's also clear to me that this is risky & will cost much time to optimize. BR Roland
If you have a moment can you test out the pull request to see if it fixes your slowdown issues?
Hi,
I tested your request and there is a huge speedup -> great work! Filling the table seems to as fast as the old gizmos version.
The only things I mentioned is:
- scrolling in a big table is still a bit slower than using the 2.8 gizmos.TreeListCtrl -> time is spent in "_paintText:DrawLabel" and "GetFullMultiLineTextExtent" (with a huge number of calls)
- closing big trees takes some time
BUT it also seems to be more reliable than the 2.8 gizmos.TreeListCtrl -> there is no "wrong drawing". So I can of course live with that.
Thank you very much!
BR Roland
What I found out is, that if I remove TR_HIDE_ROOT scrolling is much faster. And TR_VIRTUAL seems to be defective -> but maybe I'm just doing something wrong.
Can you post a program sample where the tree is still slow?
I don't think TR_VIRTUAL ever worked with HyperTreeList. The code looks broken even from 2010. If you have an example of a virtual tree that worked with the 2.8 gizmos.TreeListCtrl that would be very useful to help figure out how it should work.