Delphi TTreeView OnCustomDrawItem 事件减慢了速度
Delphi TTreeView OnCustomDrawItem event slows it down
我有一个大纲应用程序(在 Delphi 10.2 Tokyo 中)用于做笔记(我将其称为 NoteApp)。我有另一个用于编辑纯文本的应用程序 (TextApp)。由于我经常在这些应用程序之间切换,所以我决定在 TextApp 中集成笔记功能。
我copy/pasted从NoteApp到TextApp的代码,我把组件(一个TTreeView,一个TRichEdit,一个TActionToolbar)放在TextApp.Form_Main上。
TTreeView 的 OnCustomDrawItem 事件设置为根据相应注释项的 NoteType 更改每个节点的 FontStyle,它是一个简单记录数组:
type
///
/// Note types
///
TNoteType = (ntNote, ntTodo, ntDone, ntNext, ntTitle) ;
///
///
///
TNote = Record
Text ,
Attachment ,
Properties ,
CloseDate : String ;
NoteType : TNoteType ;
End;
我们的数组:
var
Notes: Array of TNote ;
以及事件:
procedure TForm_Main.TreeView_NotesCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
///
/// First check to see if the application allows us to change visuals. If the
/// application is in processing mode, visual updates are not allowed.
///
if ChangeAllowed AND Node.IsVisible then
begin
///
/// Check NoteType of the corresponding note:
///
case Notes[Node.AbsoluteIndex].NoteType of
ntTitle:
begin
TreeView_Notes.Canvas.Font.Style := [fsBold] ;
end;
//ntNote:
// begin
// end;
ntTodo:
begin
TreeView_Notes.Canvas.Font.Style := [fsBold] ;
end;
ntNext:
begin
TreeView_Notes.Canvas.Font.Style := [fsUnderline] ;
end;
ntDone:
begin
TreeView_Notes.Canvas.Font.Style := [fsStrikeOut] ;
end;
end;
end;
end;
当我在 NoteApp 中打开一个笔记文件时,它工作得很好。当我在 TextApp 中打开同一个文件时,TTreeView 刷新缓慢。 TTreeView的top item还可以,但是越往下刷新率越低。
所有组件的属性设置相同。
我怀疑我在某个地方犯了错误。我将 TextApp 上所有其他组件的可见性设置为 false,但 TTreeView 仍然非常慢。
如果我删除上面的代码,它会再次变快。我不在 TextApp 中使用运行时主题。
好的,我找到了问题的答案。
答案隐藏在上面的代码中,我发布的内容足以回答问题。原来我发布的代码毕竟是 MCVE。我发布答案以防其他人遇到这种情况。
答案:
事实证明 Node.AbsoluteIndex
非常慢。它不应该用作索引。
解决方案一:
我以前用Node.Data做索引,现在很快了
方案二:
我尝试并有效的替代解决方案:
TTreeNodeNote = class(TTreeNode)
public
Note: TNote;
end;
procedure TForm_Main.TreeView_NotesCreateNodeClass(Sender: TCustomTreeView;
var NodeClass: TTreeNodeClass);
begin
NodeClass := TTreeNodeNote;
end;
然后我们将数据存储在每个Node的Note属性中,而不是单独的数组。就像一个魅力。
我有一个大纲应用程序(在 Delphi 10.2 Tokyo 中)用于做笔记(我将其称为 NoteApp)。我有另一个用于编辑纯文本的应用程序 (TextApp)。由于我经常在这些应用程序之间切换,所以我决定在 TextApp 中集成笔记功能。
我copy/pasted从NoteApp到TextApp的代码,我把组件(一个TTreeView,一个TRichEdit,一个TActionToolbar)放在TextApp.Form_Main上。 TTreeView 的 OnCustomDrawItem 事件设置为根据相应注释项的 NoteType 更改每个节点的 FontStyle,它是一个简单记录数组:
type
///
/// Note types
///
TNoteType = (ntNote, ntTodo, ntDone, ntNext, ntTitle) ;
///
///
///
TNote = Record
Text ,
Attachment ,
Properties ,
CloseDate : String ;
NoteType : TNoteType ;
End;
我们的数组:
var
Notes: Array of TNote ;
以及事件:
procedure TForm_Main.TreeView_NotesCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
///
/// First check to see if the application allows us to change visuals. If the
/// application is in processing mode, visual updates are not allowed.
///
if ChangeAllowed AND Node.IsVisible then
begin
///
/// Check NoteType of the corresponding note:
///
case Notes[Node.AbsoluteIndex].NoteType of
ntTitle:
begin
TreeView_Notes.Canvas.Font.Style := [fsBold] ;
end;
//ntNote:
// begin
// end;
ntTodo:
begin
TreeView_Notes.Canvas.Font.Style := [fsBold] ;
end;
ntNext:
begin
TreeView_Notes.Canvas.Font.Style := [fsUnderline] ;
end;
ntDone:
begin
TreeView_Notes.Canvas.Font.Style := [fsStrikeOut] ;
end;
end;
end;
end;
当我在 NoteApp 中打开一个笔记文件时,它工作得很好。当我在 TextApp 中打开同一个文件时,TTreeView 刷新缓慢。 TTreeView的top item还可以,但是越往下刷新率越低。
所有组件的属性设置相同。
我怀疑我在某个地方犯了错误。我将 TextApp 上所有其他组件的可见性设置为 false,但 TTreeView 仍然非常慢。
如果我删除上面的代码,它会再次变快。我不在 TextApp 中使用运行时主题。
好的,我找到了问题的答案。
答案隐藏在上面的代码中,我发布的内容足以回答问题。原来我发布的代码毕竟是 MCVE。我发布答案以防其他人遇到这种情况。
答案:
事实证明 Node.AbsoluteIndex
非常慢。它不应该用作索引。
解决方案一:
我以前用Node.Data做索引,现在很快了
方案二:
我尝试并有效的替代解决方案:
TTreeNodeNote = class(TTreeNode)
public
Note: TNote;
end;
procedure TForm_Main.TreeView_NotesCreateNodeClass(Sender: TCustomTreeView;
var NodeClass: TTreeNodeClass);
begin
NodeClass := TTreeNodeNote;
end;
然后我们将数据存储在每个Node的Note属性中,而不是单独的数组。就像一个魅力。