Recent

Author Topic: TTreeView - OnCreateNodeClass & OnCustomCreateItem  (Read 934 times)

egsuh

  • Sr. Member
  • ****
  • Posts: 355
TTreeView - OnCreateNodeClass & OnCustomCreateItem
« on: March 30, 2020, 12:51:18 pm »
I tried OnCreateNodeClass alone, but this alone does not work correctly. Instead I also have to define OnCustomCreateItem event handler. For example,

Code: Pascal  [Select][+][-]
  1. procedure TOpenCoding.TV1CreateNodeClass(Sender: TCustomTreeView;
  2.    var NodeClass: TTreeNodeClass);
  3. begin
  4.     NodeClass := TOpenNode;
  5. end;
  6.  
  7. procedure TOpenCoding.TV1CustomCreateItem(Sender: TCustomTreeView;
  8.    var ATreeNode: TTreenode);
  9. begin
  10.    ATreeNode := TOpenNode.Create(Sender.Items);
  11. end;
  12.  


There are some explanations that I only have to define OnCreateNodeClass. Should I define both event handlers or am I doing something wrong?

lucamar

  • Hero Member
  • *****
  • Posts: 2824
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #1 on: March 30, 2020, 02:17:09 pm »
Both, otherwise the class you tell is created in OnCreateNodeClass and the real node item class will be different.

IIRC (I might not, it's been quite some time) it's a bug in the tree view code: it should create items of the class you tell it but it doesn't.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

martijnn

  • New Member
  • *
  • Posts: 11
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #2 on: March 31, 2020, 09:26:07 am »
I tried OnCreateNodeClass alone, but this alone does not work correctly. Instead I also have to define OnCustomCreateItem event handler.

Could you indicate a bit more what does not work correctly?

In the TCustomTreeView.CreateNode method OnCustomCreateItem is tried first when a handler is attached. In case no node instance is returned from there OnCreateNodeClass is attempted (when a handler is present). So using one of the event handlers should be sufficient.

Are you using a TTreeView or a variant (e.g. TShellTreeView) ? Which Lazarus version?

egsuh

  • Sr. Member
  • ****
  • Posts: 355
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #3 on: March 31, 2020, 09:44:55 am »
Quote
Could you indicate a bit more what does not work correctly?

With assigning only "OnCreateNodeClass", it simply fails --- class type mismatch (run-time error).

Sometimes it works fine if there are only one variable or property in the new node type (TOpenNode in my example), but not when there are more than two fields / properties.

martijnn

  • New Member
  • *
  • Posts: 11
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #4 on: March 31, 2020, 10:31:27 am »
Quote
Could you indicate a bit more what does not work correctly?

With assigning only "OnCreateNodeClass", it simply fails --- class type mismatch (run-time error).

Does that happen when accessing the nodes properties?

Quote
Could you indicate a bit more what does not work correctly?

Sometimes it works fine if there are only one variable or property in the new node type (TOpenNode in my example), but not when there are more than two fields / properties.


Can't reproduce that. Do you have a minimal code example that produces the exception?

egsuh

  • Sr. Member
  • ****
  • Posts: 355
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #5 on: March 31, 2020, 11:11:09 am »
Following is the core of the process.
Dataset is ordered by field NewCode.  If the NewCode is different from previous one, it is added as a root-level tree node, and if it is the same as the previous one, it is added as child node. But this is not an issue --- you may use loop, e.g. for i=1 to 20, etc.

Declaring "pid" as property, not a string type variable is irrelevant. I just wanted to test both field and property.

Code: Pascal  [Select][+][-]
  1.   { TOpenNode }
  2.  
  3.   TOpenNode = class(TTreeNode)
  4.   private
  5.      FPid: string;
  6.      rid,
  7.      qno,
  8.      rorder,
  9.      rcode,
  10.      NewCode,
  11.      ParentCode : integer;
  12.      RText: string;
  13.   public
  14.      property pid : string read FPid write FPid;
  15.  
  16.      procedure SaveToDB;
  17.      procedure CopyOtherNode(snode: TOpenNode);
  18.   end;
  19.  
  20.  
  21. procedure TOpenCoding.LoadCodeFrametoTV(tpid:string; DSet: TDataSet);
  22. var
  23.    nc, nc0: integer;
  24.    ntp1, ntp2 : TTreeNode;
  25. begin
  26.    with (DSet as TBufDataSet) do begin
  27.       nc0 := 0;
  28.       First;
  29.       while not eof do begin
  30.         nc := Fieldbyname('NewCode').AsInteger;
  31.         if (nc = 0) or (nc <> nc0)
  32.            then ntp1 := nil  // ntp1 is parent node.
  33.            else ntp1 := ActTV.Items.GetLastNode; //   ActTV is the name of TreeView
  34.  
  35.         ntp2 := ActTV.Items.AddChild (ntp1, FieldbyName('RText').AsString);
  36.  
  37.         with (ntp2 as TOpenNode) do begin  // <== Error occurs here.. within the with block.
  38.            pid := tpid;                                  
  39.            Rid := FieldbyName('RiD').AsInteger;
  40.            Qno := FieldbyName('Qno').AsInteger;
  41.            ROrder := FieldbyName('ROrder').AsInteger;
  42.            RCode := FieldbyName('Rcode').AsInteger;
  43.            RText := FieldbyName('RText').AsString;
  44.            NewCode := FieldbyName('NewCode').AsInteger;
  45.            ParentCode := FieldbyName('ParentCode').AsInteger;
  46.         end;
  47.  
  48.         nc0 := nc;
  49.         Next;
  50.       end; // while not cdsOpen.eof
  51.    end; // with cdsOpen
  52. end;
  53.  

martijnn

  • New Member
  • *
  • Posts: 11
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #6 on: March 31, 2020, 01:20:24 pm »
Still not reproducible. Only if OnCreateNodeClass of treeview is not assigned you'll get a runtime error.

I've attached a simple test project without using the dataset instance. Maybe you could modify it to expose the undesired behavior that you're encountering.

egsuh

  • Sr. Member
  • ****
  • Posts: 355
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #7 on: April 02, 2020, 05:49:32 am »
@martijnn,

You are right. I cannot reproduce the exception with your example. But in my own program, the exception still occurs, EInvalidCast  at line

        with (ntp2 as TOpenNode) do begin

Once I assign  OnCustomCreateItem then there are no exceptions For the time being, I'll continue looking for possible other reasons, and post here once I find it.

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3761
  • I like bugs.
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #8 on: April 02, 2020, 09:29:19 am »
@egsuh, you did not tell your Lazarus version.
IIRC this was fixed at some point.

[Edit] Ok, I didn't find any recent changed for this feature. The latest may be r48183 by Bart, already 5 years ago.
« Last Edit: April 02, 2020, 10:23:17 am by JuhaManninen »

egsuh

  • Sr. Member
  • ****
  • Posts: 355
Re: TTreeView - OnCreateNodeClass & OnCustomCreateItem
« Reply #9 on: April 03, 2020, 06:13:45 am »
I found the reason... it was because I defined OnCreateNodeClass event handler in a frame, but in the form's .lfm file, OnCreateNodeClass was set to nil under inherited TreeView1 (I should have pressed the place in the object inspector inadvertently).

What would you recommend in these cases? I have similar experiences, and in those situations, I opened .lfm file, and removed the parts of "inherited .... ".  Is this the only way?  Or would you recommend to re-assign in the forms' event handlers again, e.g. in this case, form1.oncreatenodeclass = frame1oncreatenodeclass, etc. ? It is possible but in this case I have to look for all event handlers defined in the frame, and assign all of them on the form.

 

TinyPortal © 2005-2018