[ salvaric @ 16.11.2015. 10:24 ] @
Pozdrav,

da li postoji način da se dinamički kreira Record u toku izvršavanja određeni niti na osnovu polja iz mysql tabele?

npr. da se formira :
Code:

tDataTabMesta = record
    ID : Integer;
    NAZIV: String;
    ...


Da se petljom prođe kroz tabelu i pokupe nazivi i vrste(tip polja, integer,string...) polja koji će formirati dati record.

i posle da se upotrebi kao objekat u određenoj komponenti, konkretno TVirtualStringTree.

Hteo sam malo da pojednostavim pisanje silnog koda u koliko je to izvodljivo,
da se, i u koliko dođe do izmena strukture podataka u bazi, ne menjam kod, a i imam jako puno tabela, pa da skratim muke.
[ captPicard @ 16.11.2015. 11:00 ] @
Možda ovo pomogne, davno sam bio nešto tražio i negdje pronašao:

Code (delphi):
type
  TMojiPodaci = record
    i: Integer;
    ob: TObject;
  end;
...

var
  mojrec: TMojiPodaci;
...
mojrec.i := dataset.recno;
mojrec.ob := TObject.Create;
...
mojrec.ob.Free;
[ salvaric @ 16.11.2015. 14:25 ] @
Pokušao sam na ovaj način, al ne uspeva, grešku prijavljuje u for petlji, prilikom ubacivanja podataka.

Code:

procedure TForm1.Label9Click(Sender: TObject);
var
  Data : ^TFields;
  fData: TFields;
  i: Integer;
  s: String;
  Node: PVirtualNode;
begin
     Upit.Close;
     Upit.SQL.Clear;
     Upit.SQL.Add('select * from tab_mesta');
     Upit.Open;

     TAB_MESTA.RootNodeCount:=Upit.RecordCount;
     TAB_MESTA.NodeDataSize:=SizeOf(TFields);
     ShowMessage(IntToStr(SizeOf(TFields)));
     Node := TAB_MESTA.GetFirst;

     while not Upit.EOF do
       begin
           fData := Upit.Fields;
           Data  := TAB_MESTA.GetNodeData(Node);
           Initialize(Data^);
           for i:=0 to fData.Count-1 do
             begin
                 Data^.Fields[i].Value:=fData.Fields[i].Value;
             end;

           Node:= TAB_MESTA.GetNext(Node);
           Upit.next;
       end;

end; 
[ salvaric @ 17.11.2015. 08:32 ] @
Pretpostavio sam da je na ovaj način neizvodljivo, nema druge nego sjesti i kucati.
[ Rapaic Rajko @ 17.11.2015. 10:10 ] @
Mislim da je greska ovde, sizeof klase je besmislen.

Code:

  TAB_MESTA.NodeDataSize:=SizeOf(TFields);


Sta je uopste NodeDataSize, ukupan broj node-ova ili nesto drugo?

Pozz



[ salvaric @ 17.11.2015. 11:59 ] @
"NodeDataSize" je SizeOf(TData) gde je TData = record ..., a "Data:=TAB_MESTA.GetNodeData(Node)" gde je Data = ^TData.

To sam naveo samo na primeru šta hoću da izvedem, znam da ovo nije moguće.
[ Rapaic Rajko @ 17.11.2015. 13:32 ] @
Naravno da je moguce, SVE je moguce.

1) Ne koriste se nazivi Delphi klasa i tipova za svoje/izvedene klase i tipove. TFields preimenuj u TDataFields. Ili ti fData upravo JESTE instanca Delphi TFields klase?
2) Ne ide Initialize(Data^) vec new(Data), sto upravo alocira memoriju za record (cijim podacima pristupas sa Data^).
3) Ni ovo pod 2) nije dovoljno ako imas 'pravi' TFields, moras da kreiras instancu TFields; recimo u metodi record-a.
4) Daj deklaraciju TData record-a pa da popravimo sta se moze. .
5) Zasto ne upotrebis klasu umesto record-a? Onda se ne mlatis sa pointerima, nego kroz poziv konstruktora klase pravis i instancu Fields (DataFields := TFields.Create).

Pozz
[ salvaric @ 18.11.2015. 08:17 ] @
Hvala Rajko na edukaciji i na pomoći.

Ne znam dal sam spomenuo da koristim Lazarus.
Na stranici link je prikazan primer kako funkcioniše prikaz VirtialStringTree komponente koju koristim.

Moja zamisao je da kreiram dinamički record na osnovu polja u tabeli (mysql), u momentu kad se zatraži prikaz date komponente.

Code:
Data:=VST.GetNodeData(Node);
poziva funkciju :
Code:

function TBaseVirtualTree.GetNodeData(Node: PVirtualNode): Pointer;
// Returns the address of the user defined data area in the node.
begin
  Assert(FNodeDataSize > 0, 'NodeDataSize not initialized.');
  if (FNodeDataSize <= 0) or (Node = nil) or (Node = FRoot) then
    Result := nil
  else
    Result := PByte(@Node.Data) + FTotalInternalDataSize;
end;


Sad ne znam dal se može u taj "Data" smestiti klasa umesto record-a.
[ salvaric @ 18.11.2015. 08:45 ] @
Code:

  TVirtualNode = record
    Index,                   // index of node with regard to its parent
    ChildCount: Cardinal;    // number of child nodes
    NodeHeight: Word;        // height in pixels
    States: TVirtualNodeStates; // states describing various properties of the node (expanded, initialized etc.)
    Align: Byte;             // line/button alignment
    CheckState: TCheckState; // indicates the current check state (e.g. checked, pressed etc.)
    CheckType: TCheckType;   // indicates which check type shall be used for this node
    Dummy: Byte;             // dummy value to fill DWORD boundary
    TotalCount,              // sum of this node, all of its child nodes and their child nodes etc.
    TotalHeight: Cardinal;   // height in pixels this node covers on screen including the height of all of its
                             // children
    // Note: Some copy routines require that all pointers (as well as the data area) in a node are
    //       located at the end of the node! Hence if you want to add new member fields (except pointers to internal
    //       data) then put them before field Parent.
    Parent,                  // reference to the node's parent (for the root this contains the treeview)
    PrevSibling,             // link to the node's previous sibling or nil if it is the first node
    NextSibling,             // link to the node's next sibling or nil if it is the last node
    FirstChild,              // link to the node's first child...
    LastChild: PVirtualNode; // link to the node's last child...
    Data: record end;        // this is a placeholder, each node gets extra data determined by NodeDataSize
  end; 
[ salvaric @ 18.11.2015. 09:32 ] @
Rešio sam problem uz Rajkovu pomoć, još jednom hvala!!!

Code:

type
  TCusField = class
     Value : String;
     ...
  end;

type
  PData = ^TData;
  TData = record
     Field : array of TCusField;
  end;  
...

//prilikom učitavanja:

procedure UčitajTabelu;
var
  Data : PData;
  i: Integer;
  Node: PVirtualNode;
  CustField: TCusField;
begin
     modul_zeos.Upit.Close;
     modul_zeos.Upit.SQL.Clear;
     modul_zeos.Upit.SQL.Add('select * from tab_mesta');
     modul_zeos.Upit.Open;

     TAB_FIRME.RootNodeCount:=modul_zeos.Upit.RecordCount;

     TAB_FIRME.NodeDataSize:=SizeOf(TData);

     Node := TAB_FIRME.GetFirst;

     while not modul_zeos.Upit.EOF do
       begin
           Data:= TAB_FIRME.GetNodeData(Node);
           Initialize(Data^);
           for i:=0 to  modul_zeos.Upit.FieldCount-1 DO
              begin
               SetLength(Data^.Field,modul_zeos.Upit.FieldCount);
               CustField:=TCusField.Create;
               CustField.Value:=modul_zeos.Upit.Fields[i].AsString;
               Data^.Field[i]:=CustField;
              end;
           Node:= TAB_FIRME.GetNext(Node);
           modul_zeos.Upit.next;
       end;

end; 
[ Rapaic Rajko @ 18.11.2015. 11:28 ] @
Cestitam!

Ali obrati paznju: ko je odgovoran za instance TCusField koje kreiras u petlji, odnosno ko ih unistava (cisti memoriju) prilikom zatvaranja forme, ili prilikom reload-a pomenute komponente itd.?
Dok to ne resis, imaces moguce curenje memorije (nedealocirane instance TCusField klase).

Jedno moguce resenje je da klasu izvedes od TComponent, i da je kreiras ovako (pod pretpostavkom da je TAB_FIRME instanca klase TVirtualStringTree):

Code:

    CusField := TCusField.Create(TAB_FIRME); // ili, umesto TAB_FIRME podmetnuti formu na kojoj se sve nalazi


Zasto bi ovo trebalo da radi? Zato sto SVAKI komponent ima property Components, koji se unistava kad i sam komponent. Na taj nacin, instance TCusField se gomilaju (priliko svakog reload-a), ali kad se forma zatvori, sve se to pocisti.

A drugi nacin je da potrazis neki odgovarajuci event komponente TAB_FORME, u kojem ces ubaciti ovakav kod:

Code:

    ...
    Data:= TAB_FIRME.GetNodeData(Node);
    TCusField(Data^.Field[i]).Free;
    ....


Pozz (i svaka cast!)
[ salvaric @ 18.11.2015. 12:34 ] @
Ova komponenta ima event "FreeNode" koji sve rešava:

Code:
procedure TForm1.TAB_FIRMEFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode
  );
  Var
  Data: PData;
  i: Integer;
begin
      Data:=Sender.GetNodeData(Node);
      If Assigned(Data) then
        for i:=0 to High(Data^.Field) do
         Data^.Field[i].Free;
end; 


Tako da hvala u svakom slučaju!