加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – VirtualStringTree – 指针存储<>指针检索!我

发布时间:2020-12-15 09:28:41 所属栏目:大数据 来源:网络整理
导读:我正在使用TVirtualStringTree来存储指向记录的指针. 最初有一个包含记录列表的TList. 我正在使用OnInitNode事件迭代TList并将每个记录的数据分配给树的节点. 但是,在检索与OnNewText事件处理程序中的节点关联的数据时,返回的指针具有与最初存储在树中的指针
我正在使用TVirtualStringTree来存储指向记录的指针.

最初有一个包含记录列表的TList.

我正在使用OnInitNode事件迭代TList并将每个记录的数据分配给树的节点.

但是,在检索与OnNewText事件处理程序中的节点关联的数据时,返回的指针具有与最初存储在树中的指针不同的地址.

此外,我可以通过调试看到从节点检索的指针(到记录数据)与最初存储在节点中的指针不同.我需要将更改的数据保存到数据库,并需要使用更改的数据引用记录.引用指针应该很简单,但问题是指针不一样.

我不确定我做错了什么,希望有人可以帮我解决这个问题.

提前致谢.

这是我的代码:

数据结构和声明:

TTherapData = record
    TherapID: Integer;
    TherapName: String[120];
    TherapInstr: String[120];
    Selected_DB: Byte;
    Selected: Byte;
  end;

  PTherapData = ^TTherapData;

  FTherapDataList: TList<PTherapData>;

  FTherapDataListAsg_Iter: Integer;

  vstRxList_Asg: TVirtualStringTree;

将数据加载到TList中,然后加载到树中:

procedure TfmPatient_Conslt.LoadTherapList(const ADBLoad: Boolean = False);
var
  TherapData: PTherapData;
  d,x: Integer;
begin
    datamod.uspLKTHERAP_S.First;
    while not datamod.uspLKTHERAP_S.Eof do
    begin
      New(TherapData);

      TherapData^.TherapID := datamod.uspLKTHERAP_SROW_ID.AsInteger;
      TherapData^.TherapName := datamod.uspLKTHERAP_SIMPRTHERAP.AsString;
      TherapData^.TherapInstr := EmptyStr;
      TherapData^.Selected := 0;
      TherapData^.Selected_DB := 0;

      FTherapDataList.Add(TherapData);

      datamod.uspLKTHERAP_S.Next;
    end;


    datamod.uspCONSLT_RX_S.First;
    while not datamod.uspCONSLT_RX_S.Eof do
    begin
      d := datamod.uspCONSLT_RX_SRX_ID.AsInteger;
      TherapData := FTherapDataList[TherapDataList_GetIndexOfID(d)];
      TherapData^.TherapInstr := datamod.uspCONSLT_RX_SRX_INSTRUCTION.AsString;
      TherapData^.Selected := 1;
      TherapData^.Selected_DB := 1;

      datamod.uspCONSLT_RX_S.Next;
    end;

  x := TherapDataList_CountSelectedItems;

  FTherapDataListAsg_Iter := 0;
  vstRxList_Asg.NodeDataSize := SizeOf(TTherapData);
  vstRxList_Asg.RootNodeCount := 0;
  vstRxList_Asg.RootNodeCount := x;
end;

procedure TfmPatient_Conslt.vstRxList_AsgInitNode(Sender: TBaseVirtualTree; ParentNode,Node: PVirtualNode;
  var InitialStates: TVirtualNodeInitStates);
var
  TherapData: PTherapData;
begin
  TherapData := Sender.GetNodeData(Node);

  while (FTherapDataList[FTherapDataListAsg_Iter]^.Selected <> 1) do
    Inc(FTherapDataListAsg_Iter);

  TherapData^.TherapID := FTherapDataList[FTherapDataListAsg_Iter]^.TherapID;
  TherapData^.TherapName := FTherapDataList[FTherapDataListAsg_Iter]^.TherapName;
  TherapData^.TherapInstr := FTherapDataList[FTherapDataListAsg_Iter]^.TherapInstr;

  { TherapData := FTherapDataList[FTherapDataListAsg_Iter]; } //  
  { TherapData^ := FTherapDataList[FTherapDataListAsg_Iter]^; } //  

  Inc(FTherapDataListAsg_Iter);
end;

procedure TfmPatient_Conslt.vstRxList_AsgGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType; var CellText: string);
var
  TherapData: PTherapData;
begin
  TherapData := Sender.GetNodeData(Node);
  if Assigned(TherapData) then
    if (Column = 0) then
      CellText := TherapData^.TherapName
    else if (Column = 1) then
      CellText := TherapData^.TherapInstr;
end;

procedure TfmPatient_Conslt.vstRxList_AsgEditing(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
  var Allowed: Boolean);
begin
  Allowed := (Column = 1);
end;

检索数据.我注意到这里的问题:

procedure TfmPatient_Conslt.vstRxList_AsgNewText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
  NewText: string);
var
  TherapData: PTherapData;
begin

  if (Column = 1) then
  begin
    TherapData := Sender.GetNodeData(Node);
    if Assigned(TherapData) then                 // <---- There is a debug breakpoint here 
                                                 // and the watch window screen-shot 
                                                 // is taken here
      TherapData^.TherapInstr := NewText;

    // Showmessage(Format('%p',[TherapData]));  // <---- The pointer value is not the same
                                                 //       as that originally stored !

  end;

end;

这是我将列表数据保存到数据库的地方,以及我需要树来更改原始数据而不是副本的原因:

procedure TfmPatient_Conslt.SaveRxListToDB;
var
  TherapData: PTherapData;
begin

  for TherapData in FTherapDataList do
  begin
    if (TherapData^.Selected = 1) and (TherapData^.Selected_DB = 0) then
    begin
      // Add new entries to DB
      // :ROW_ID,:CONSLT_ID,:RX_ID,:RX_INSTRUCTION
      datamod.uspCONSLT_RX_I.ParamByName('ROW_ID').AsInteger := 0;
      datamod.uspCONSLT_RX_I.ParamByName('CONSLT_ID').AsInteger := FConsultationID;
      datamod.uspCONSLT_RX_I.ParamByName('RX_ID').AsInteger := TherapData^.TherapID;
      datamod.uspCONSLT_RX_I.ParamByName('RX_INSTRUCTION').AsString := TherapData^.TherapInstr;
      datamod.uspCONSLT_RX_I.PrepareSQL(False);
      datamod.uspCONSLT_RX_I.ExecProc;

      TherapData^.Selected_DB := 1;
    end
    else if (TherapData^.Selected = 1) and (TherapData^.Selected_DB = 1) then
    begin
      // Update existing DB entries
      // :CONSLT_ID,:RX_INSTRUCTION
      datamod.uspCONSLT_RX_U.ParamByName('CONSLT_ID').AsInteger := FConsultationID;
      datamod.uspCONSLT_RX_U.ParamByName('RX_ID').AsInteger := TherapData^.TherapID;
      datamod.uspCONSLT_RX_U.ParamByName('RX_INSTRUCTION').AsString := TherapData^.TherapInstr;
      datamod.uspCONSLT_RX_U.PrepareSQL(False);
      datamod.uspCONSLT_RX_U.ExecProc;
    end
    else if (TherapData^.Selected = 0) and (TherapData^.Selected_DB = 1) then
    begin
      // Delete removed entries from DB
      // :CONSLT_ID,:RX_ID
      datamod.uspCONSLT_RX_D.ParamByName('CONSLT_ID').AsInteger := FConsultationID;
      datamod.uspCONSLT_RX_D.ParamByName('RX_ID').AsInteger := TherapData^.TherapID;
      datamod.uspCONSLT_RX_D.PrepareSQL(False);
      datamod.uspCONSLT_RX_D.ExecProc;

      TherapData^.Selected_DB := 0;
    end;
  end;

end;

以下是Debug-> Watch List窗口的屏幕截图:

解决方法

要回答标题中的问题,我会说是的,你的编码方法是错误的.

错误是您没有将指向数据记录的指针保存到VT的节点,而是为每个节点分配整个(单独的)TTherapData记录!所以“错误”就是这条线

vstRxList_Asg.NodeDataSize := SizeOf(TTherapData);

在TfmPatient_Conslt.LoadTherapList方法中.你可能想要的是一个附加记录,它保存指向数据记录的指针:

type
  TVTNodeData = record
    TherapData: PTherapData;
  end;
  PVTNodeData = ^TVTNodeData;

并将该记录用作节点数据记录:

vstRxList_Asg.NodeDataSize := SizeOf(TVTNodeData);

和节点init变成类似的东西

procedure TfmPatient_Conslt.vstRxList_AsgInitNode(Sender: TBaseVirtualTree; ParentNode,Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  NodeData: PVTNodeData;
begin
  NodeData := Sender.GetNodeData(Node);

  while (FTherapDataList[FTherapDataListAsg_Iter]^.Selected <> 1) do
    Inc(FTherapDataListAsg_Iter);

  NodeData^.TherapData := FTherapDataList[FTherapDataListAsg_Iter];

  Inc(FTherapDataListAsg_Iter);
end;

并使用其他树事件中的数据

procedure TfmPatient_Conslt.vstRxList_AsgGetText(Sender: TBaseVirtualTree; Node:PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  NodeData: PVTNodeData;
  TherapData: PTherapData;
begin
  NodeData := Sender.GetNodeData(Node);
  if Assigned(NodeData) and Assigned(NodeData.TherapData) then begin
    TherapData := NodeData.TherapData;
    if (Column = 0) then
      CellText := TherapData^.TherapName
    else if (Column = 1) then
      CellText := TherapData^.TherapInstr;
  end;
end;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读