捐赠 | 广告 | 注册 | 发布 | 上传 | 关于我们    
  粤ICP备10103342号-1 DELPHI盒子 | 盒子文章 | 盒子问答悬赏 | 最新更新 | 盒子检索 | 下载中心 | 高级搜索    
  精品专区 | 繁體中文 | 奖励公告栏 | 直通车账号登陆 | 关闭GOOGLE广告 | 临时留言    
 
广告
评论:Treeview与数据库的联合使用实例
laijiabo 41829 2011/9/6 17:06:11
为什么我换了SQL SERVER数据库就出错了
logitech1229 25916 2006/9/7 16:23:11
有一个我觉得有必要说的问题就是我每一次拖动类别并保存异动之后都要重新FillTree一次。几十条还无所谓,几百条的时候就不爽了。另外明显感觉到刷屏,看上去不舒服。不知道Windows的资源管理器如何做的?肯定不是重新建立Tree结构的。
leon8140473 24870 2006/7/12 1:10:57
为什么要拖动啊 单机还没什么问题 网络版的累死啊``
还有有下级当然不能删除上级了
lusoja 23716 2006/5/19 14:04:15
非常感谢! 我已将大家的思路和代码应用到我的设计中了。
在此还向大家请教: 我加了一个字段,是做备注用的(文本型),现在我想能在同级结点间进行移动。 又该如何设计呢?
johnson588 21668 2006/2/20 17:32:41
这么好的东西拿出来,真要好好谢谢你啊。
zyt_xj 13453 2005/3/23 11:30:38
为什么我换了SQL SERVER数据库就出错了
m0use 9009 2004/10/31 11:56:08
真的很不错..只要把表扩充了一下就可以用得很爽。
不过有个问题.怎么才能把速度加快...我二百条记录用了十秒钟。有办法解决吗?
初学DELPHI,甚多不懂,谢谢作者。
ac97 8228 2004/9/7 6:46:24
很好我学会了引用, 并用它做了一个程序,  我又加入了一个表, 但没弄明白,  删除一个根节点时,  所有子节点的节点号存在那里?   因为在另一个表中也要同步清除.  谢谢.
ac97 5881 2004/6/9 22:00:17
能告诉我在我的程序中怎样引用后面的这两个单元文件吗?
我照搬了窗体和数据模块,  但是在搬后面的两个单元时不知如果将其加入我的程序~~
studydephi 5544 2004/6/2 11:40:45
很好,谢谢,我都想了两天了!
kwbin 4626 2004/5/5 21:46:27
全贴完了
kwbin 4625 2004/5/5 21:42:59
unit TreeUtils;

interface
uses
  Windows, Messages, SysUtils, Variants, Classes, ComCtrls, DB, ADODB,
  TreeFillThrd; //注意
type
  TTreeUtils = class
    TreeView: TTreeView;
    NData: TNodeData;
    Conn: TADOConnection;
    Query: TADOQuery;
    constructor Create(ATree: TTreeView; AConn: TADOConnection; ATableName: string;
      AFieldIndex: string = 'ID'; AFieldPID: string = 'PID';
      AFieldCaption: string = 'Caption'; ARootText: string = '我的目录');
    destructor Destroy;
  private
    TableName: string;
    FieldIndex: string;
    FieldPID: string;
    FieldCaption: string;
    RootText: string;
    sqlStr, errStr: string;
    function getMaxIndex: integer;
    function execSQL(sqlStr: string; var errMsg: string): boolean;
  public
    //按照节点在数据库中的编号查找节点
    function FindTreeNode(Tree: TTreeView; Index: integer): TTreeNode;
    //删除子树
    function DeleteTree(Node: TTreeNode): Boolean;
    //查找节点在数据库中的数据
    function getTreeNodeData(TreeNode: TTreeNode): TNodeData;
    function getSelNodeIndex: integer;
    function getSelNodeCaption: string;
    //添加节点
    function AddNode(ACaption: string = '新节点'; ANode: TTreeNode = nil): Boolean;
    function AddChildNode(ACaption: string = '新节点'; ANode: TTreeNode = nil): Boolean;
    //修改节点
    function ModifyNodeCaption(NewCaption: string; Node: TTreeNode): boolean;
    function ModifyNodePID(PID: integer; Node: TTreeNode): boolean;
    //填充节点
    procedure FillTree;
  end;

implementation
//--------------------------------------------------------------
constructor TTreeUtils.Create(ATree: TTreeView; AConn: TADOConnection; ATableName: string;
  AFieldIndex: string = 'ID'; AFieldPID: string = 'PID';
  AFieldCaption: string = 'Caption'; ARootText: string = '我的目录');
begin
  TreeView := ATree;
  Conn := AConn;
  TableName := ATableName;
  FieldIndex := AFieldIndex;
  FieldPID := AFieldPID;
  FieldCaption := AFieldCaption;
  RootText := ARootText;
  Query := TADOQuery.Create(nil);
  Query.Connection := Conn;
end;
//--------------------------------------------------------------
destructor TTreeUtils.Destroy;
begin
  Query.Free;
  inherited Destroy;
end;
//--------------------------------------------------------------
function TTreeUtils.FindTreeNode(Tree: TTreeView; Index: integer): TTreeNode;
var i: integer;
begin
  Result := nil;
  for i := 0 to Tree.Items.Count - 1 do
    if PNodeData(Tree.Items.Item[i].Data)^.Index = Index then
      Result := Tree.Items.Item[i];
end;
//--------------------------------------------------------------
function TTreeUtils.DeleteTree(Node: TTreeNode): Boolean;
  function DelTableFromIndex(index: integer): boolean;
  var
    sqlStr: string;
    errSTr: string;
  begin
    Result := False;
    SQLStr := 'Delete from ' + TableName + ' where ' + FieldIndex + ' = ' + IntToStr(index);
    if execSQL(sqlStr, errStr) then Result := True;
  end;
  //------------------------------------------------------------
  function DelTreeFromDB(ParentID: integer): Boolean;
  var Query: TADOQuery;
  begin
    Query := nil;
    Result := False;
    try
      Query := TADOQuery.Create(nil);
      Query.Connection := Conn;
      Query.SQL.Text := 'select * from ' + TableName + ' where PID = ' + IntToStr(ParentID);
      if Query.Active then Query.Close;
      Query.Open;
      while Query.Eof = False do
      begin
        DelTreeFromDB(Query.FieldValues[FieldIndex]);
        Result := DelTableFromIndex(Query.FieldByName(FieldIndex).AsInteger);
        Query.Next;
      end;
    finally
      Query.Free;
    end;
    Result := DelTableFromIndex(ParentID);
  end;
  //------------------------------------------------------------
begin
  Result := False;
  if Node.AbsoluteIndex = 0 then
  begin
    raise Exception.Create('禁止删除根节点!');
    Exit;
  end;
  if DelTreeFromDB(PNodeData(Node.Data)^.Index) then
  begin
    TreeView.Items.Delete(Node);
    Result := True;
  end;
end;
//--------------------------------------------------------------
function TTreeUtils.getTreeNodeData(TreeNode: TTreeNode): TNodeData;
begin
  if TreeNode = nil then
    Result := PNodeData(TreeView.Items.Item[0].Data)^
  else
    Result := PNodeData(TreeNode.Data)^;
end;
//--------------------------------------------------------------
function TTreeUtils.getSelNodeIndex: integer;
var PData: PNodeData;
begin
  Result := -1;
  if TreeView.Selected = nil then Exit;
  PData := PNodeData(TreeView.Selected.Data);
  Result := PData^.Index;
end;
function TTreeUtils.getSelNodeCaption: string;
var PData: PNodeData;
begin
  Result := ';
  if TreeView.Selected = nil then Exit;
  PData := PNodeData(TreeView.Selected.Data);
  Result := PData^.Caption;
end;
//--------------------------------------------------------------
function TTreeUtils.AddNode(ACaption: string = '新节点'; ANode: TTreeNode = nil): Boolean;
var Node, NewNode: TTreeNode;
  PData: PNodeData;
begin
  Result := True;
  try
    if ANode = nil then Node := TreeView.Selected
    else Node := ANode;
    New(PData);
    PData^.Index := getMaxIndex + 1;
    PData^.Caption := ACaption;
    sqlStr := 'Insert into ' + TableName + ' (' + FieldIndex + ',' + FieldPID +
      ',' + FieldCaption + ')' + ' values(' +
      IntToStr(PData^.Index) + ',';
    if Node = nil then Node := TreeView.Items.Item[0];
    if Node.Level = 0 then
      sqlStr := sqlStr + '0,"' + ACaption + '")'
    else
      sqlStr := sqlStr + IntToStr(PNodeData(Node.Parent.Data)^.Index) + ',"' + ACaption + '")';
    if execSQL(sqlStr, errStr) then
    begin
      if Node.Level = 0 then
        NewNode := TreeView.Items.AddChildObject(Node, ACaption, PData)
      else NewNode := TreeView.Items.AddObject(Node, ACaption, PData);
      NewNode.ImageIndex := 1;
      NewNode.SelectedIndex := 2;
    end;
  except
    Result := False;
  end;
end;
//--------------------------------------------------------------
function TTreeUtils.AddChildNode(ACaption: string = '新节点';
  ANode: TTreeNode = nil): Boolean;
var Node, NewNode: TTreeNode;
  PData: PNodeData;
begin
  Result := True;
  try
    if ANode = nil then Node := TreeView.Selected
    else Node := ANode;
    New(PData);
    PData^.Index := getMaxIndex + 1;
    PData^.Caption := ACaption;
    sqlStr := 'Insert into ' + TableName + ' (' + FieldIndex + ',' + FieldPID +
      ',' + FieldCaption + ')' + ' values(' +
      IntToStr(PData^.Index) + ',';
    if Node = nil then Node := TreeView.Items.Item[0];
    if Node.Level = 0 then
      sqlStr := sqlStr + '0,"' + ACaption + '")'
    else
      sqlStr := sqlStr + IntToStr(PNodeData(Node.Data)^.Index) + ',"' + ACaption + '")';
    if execSQL(sqlStr, errStr) then
    begin
      NewNode := TreeView.Items.AddChildObject(Node, ACaption, PData);
      NewNode.ImageIndex := 1;
      NewNode.SelectedIndex := 2;
    end;

  except
    Result := False;
  end;
end;
//--------------------------------------------------------------
//执行SQL语言
function TTreeUtils.execSQL(sqlStr: string; var errMsg: string): boolean;
begin
  result := false;
  errMsg := '执行成功!';
  try
    Query.SQL.Text := sqlStr;
    if Query.Active then Query.Close;
    Query.ExecSQL;
    result := true;
  except
    on e: Exception do
      errMsg := e.Message;
  end;
end;
//------------------------------------------------------------------------------
function TTreeUtils.getMaxIndex: integer;
var i: integer;
  PNode: PNodeData;
begin
  Result := 0;
  for i := 0 to TreeView.Items.Count - 1 do
  begin
    PNode := PNodeData(TreeView.Items.Item[i].Data);
    if Result < PNode^.Index then
      Result := PNode^.Index;
  end;
end;
//------------------------------------------------------------------------------
procedure TTreeUtils.FillTree;
var H: TTreeFill;
begin
  H := TTreeFill.Create(TreeView, Conn, TableName, RootText, FieldIndex, FieldPID, FieldCaption);
end;
//------------------------------------------------------------------------------
function TTreeUtils.ModifyNodeCaption(NewCaption: string;
  Node: TTreeNode): boolean;
begin
  sqlStr := 'Update ' + TableName + ' set ' + FieldCaption + '="' + NewCaption + '" where '
    + FieldIndex + ' = ' + IntToStr(PNodeData(Node.Data)^.Index);
  if execSQL(sqlStr, errStr) then
  begin
    Node.Text := NewCaption;
    PNodeData(Node.Data)^.Caption := NewCaption;
  end;
end;
//------------------------------------------------------------------------------
function TTreeUtils.ModifyNodePID(PID: integer; Node: TTreeNode): boolean;
  function InChildNode(APID: integer; ANode: TTreeNode): boolean;
  var loop, NStart, NEnd: integer;
  begin
    Result := False;
    NStart := Node.AbsoluteIndex;
    if Node.getNextSibling = nil then NEnd := TreeView.Items.Count - 1
    else NEnd := Node.GetNextSibling.AbsoluteIndex;
    for loop := NStart + 1 to NEnd - 1 do
    begin
      Result := Result or (PNodeData(TreeView.Items.Item[loop].Data)^.Index = PID);
    end;
  end;
begin
  Result := False;
  //如果是根节点则忽略
  if Node.AbsoluteIndex = 0 then Exit;
  //如果PID不变则忽略
  if PID = PNodeData(Node.Parent.Data)^.Index then Exit;
  //如果父节点是自己也则忽略
  if PID = PNodeData(Node.Data)^.Index then Exit;
  //如果父节点编号是它其中一级子节点的编号,则忽略
  if InChildNode(PID, Node) then Exit;
  sqlStr := 'Update ' + TableName + ' set ' + FieldPID + '="' + IntToStr(PID) + '" where '
    + FieldIndex + ' = ' + IntToStr(PNodeData(Node.Data)^.Index);
  if execSQL(sqlStr, errStr) then Result := True;
end;

end.

kwbin 4624 2004/5/5 21:42:17
unit TreeFillThrd;

interface

uses
  Classes, ComCtrls, ADODB, SysUtils;

type
  TNodeData = record
    Index: integer;
    Caption: string;
  end;
  PNodeData = ^TNodeData;
  TTreeFill = class(TThread)
    TV: TTreeView;
    TableName: string;
    FieldIndex: string;
    FieldPID: string;
    FieldCaption: string;
    RootText: string;
    Conn: TADOConnection;
    Ptr: PNodeData;
    constructor Create(ATreeView: TTreeView; AConn: TADOConnection;
      ATable: string; ARootText: string = '我的目录';
      AFieldIndex: string = 'ID'; AFieldPID: string = 'PID';
      AFieldCaption: string = 'Caption');
  private
    procedure AddTree(Node: TTreeNode; PN: PNodeData);
  protected
    procedure Execute; override;
  end;

implementation
//------------------------------------------------------------------------------
constructor TTreeFill.Create(ATreeView: TTreeView; AConn: TADOConnection;
  ATable: string; ARootText: string = '我的目录';
  AFieldIndex: string = 'ID'; AFieldPID: string = 'PID';
  AFieldCaption: string = 'Caption');
begin
  FieldIndex := AFieldIndex;
  FieldPID := AFieldPID;
  FieldCaption := AFieldCaption;
  TV := ATreeView;
  TableName := ATable;
  RootText := ARootText;
  Conn := AConn;
  New(Ptr);
  inherited Create(False);
end;
//------------------------------------------------------------------------------
procedure TTreeFill.Execute;
var
  Node: TTreeNode;
begin
  FreeOnTerminate := True;
  TV.Items.Clear;
  Ptr^.Index := 0;
  Ptr^.Caption := RootText;
  Node := TV.Items.AddObject(nil, RootText, Ptr);
  Node.ImageIndex := 0;
  Node.SelectedIndex := 0;
  AddTree(Node, Ptr);
  TV.FullExpand;
end;
//------------------------------------------------------------------------------
procedure TTreeFill.AddTree(Node: TTreeNode; PN: PNodeData);
var Query: TADOQuery;
  nNode: TTreeNode;
  PNode: PNodeData;
begin
  try
    Query := TADOQuery.Create(nil);
    Query.Connection := Conn;
    Query.SQL.Text := 'Select * from ' + TableName + ' where ' + FieldPID + ' =' + IntToStr(PN^.Index);
    if Query.Active then
      Query.Close;
    Query.Open;
    while Query.Eof = False do
    begin
      New(PNode);
      PNode^.Caption := Query.FieldByName(FieldCaption).AsString;
      PNode^.Index := Query.FieldByName(FieldIndex).AsInteger;
      nNode := TV.Items.AddChildObject(Node, PNode^.Caption, PNode);
      nNode.ImageIndex := 1;
      nNode.SelectedIndex := 2;
      AddTree(nNode, PNode);
      Query.Next;
    end;
  finally
    Query.Free;
  end;
end;
//------------------------------------------------------------------------------
end.

kwbin 4623 2004/5/5 21:41:36
unit frmMainUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, Buttons,
  TreeUtils, ActnList, ExtCtrls, ImgList, Menus;

type
  TfrmMain = class(TForm)
    TreeView1: TTreeView;
    StatusBar1: TStatusBar;
    ActionList1: TActionList;
    acAdd: TAction;
    acAddChild: TAction;
    Panel1: TPanel;
    ImageList1: TImageList;
    Panel2: TPanel;
    btnDelete: TButton;
    btnAddChild: TBitBtn;
    btnAdd: TBitBtn;
    edtCaption: TEdit;
    Label2: TLabel;
    Panel3: TPanel;
    acDelete: TAction;
    PopupMenu1: TPopupMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;
    Label1: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    lblNodeCaption: TLabel;
    lblNodeIndex: TLabel;
    lblParentCaption: TLabel;
    lblParentIndex: TLabel;
    Bevel1: TBevel;
    Splitter1: TSplitter;
    acEdit: TAction;
    N4: TMenuItem;
    N5: TMenuItem;
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure FormCreate(Sender: TObject);
    procedure acAddExecute(Sender: TObject);
    procedure acAddChildExecute(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure acDeleteExecute(Sender: TObject);
    procedure TreeView1Edited(Sender: TObject; Node: TTreeNode;
      var S: string);
    procedure acEditExecute(Sender: TObject);
    procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
    TreeUtil: TTreeUtils;
  end;

var
  frmMain: TfrmMain;

implementation

uses DMUnit, TreeFillThrd;

{$R *.dfm}

procedure TfrmMain.TreeView1Change(Sender: TObject; Node: TTreeNode);
var Nod: TNodeData;
  // S: string;
begin
  //  S := 'AbsIndex:[' + IntToStr(TreeView1.Selected.AbsoluteIndex);
  //  S := S + '] Text:[' + TreeView1.Selected.Text;
  //  S := S + '] Index:[' + IntToStr(TreeUtil.getSelNodeIndex);
  //  S := S + '] Caption:[' + TreeUtil.getSelNodeCaption + ']';
  //  S := S + '] Caption:[' + PNodeData(TreeView1.Selected.Data)^.Caption;
  //  StatusBar1.Panels.Items[0].Text := S;
  lblNodeCaption.Caption := TreeUtil.getSelNodeCaption;
  lblNodeIndex.Caption := IntToStr(TreeUtil.getSelNodeIndex);
  Nod := TreeUtil.getTreeNodeData(TreeView1.Selected.Parent);
  lblParentCaption.Caption := Nod.Caption;
  lblParentIndex.Caption := IntToStr(Nod.Index);
end;

procedure TfrmMain.acEditExecute(Sender: TObject);
begin
  TreeView1.Selected.EditText;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  TreeUtil := TTreeUtils.Create(TreeView1, DM.Conn, 'Dir');
  TreeUtil.FillTree;
end;

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  TreeUtil.Free;
end;

procedure TfrmMain.acAddExecute(Sender: TObject);
begin
  TreeUtil.AddNode(edtCaption.Text);
end;

procedure TfrmMain.acAddChildExecute(Sender: TObject);
begin
  TreeUtil.AddChildNode(edtCaption.Text);
end;

procedure TfrmMain.acDeleteExecute(Sender: TObject);
begin
  if MessageBox(handle, PChar('你确认要删除"' + TreeView1.Selected.Text + '"吗?'),
    '提示', MB_ICONQUESTION + MB_YESNO) = IDYES then
    TreeUtil.DeleteTree(TreeView1.Selected);
end;

procedure TfrmMain.TreeView1Edited(Sender: TObject; Node: TTreeNode;
  var S: string);
begin
  //修改Node的文本
  TreeUtil.ModifyNodeCaption(S, Node)
end;

procedure TfrmMain.TreeView1DragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
begin
  if Source = TreeView1 then Accept := True
  else Accept := False;
end;

procedure TfrmMain.TreeView1DragDrop(Sender, Source: TObject; X,
  Y: Integer);
var TargetNode, SourceNode: TTreeNode;
begin
  TargetNode := TreeView1.DropTarget;
  SourceNode := TreeView1.Selected;
  if MessageBox(handle, '您确认要异动目录吗?', '提示', MB_ICONQUESTION
    + MB_YESNO) = IDYES then
    if TreeUtil.ModifyNodePID(PNodeData(TargetNode.Data)^.Index, SourceNode) then
      TreeUtil.FillTree;
end;

end.

kwbin 4622 2004/5/5 21:41:03
unit DMUnit;

interface

uses
  SysUtils, Classes, DB, ADODB;

type
  TDM = class(TDataModule)
    Conn: TADOConnection;
    procedure DataModuleCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DM: TDM;

implementation

{$R *.dfm}

procedure TDM.DataModuleCreate(Sender: TObject);
begin
  if Conn.Connected then Conn.Close;
  conn.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;' +
    'Jet OLEDB:Database Password= ; Data Source=' +
    ExtractFilePath(ParamStr(0)) + 'data\Dir.mdb;' +
    ';Persist Security Info=False';
  conn.Open;
end;

end.
kwbin 4621 2004/5/5 21:36:54
program TreeView;

uses
  Forms,
  frmMainUnit in 'frmMainUnit.pas' {frmMain},
  TreeUtils in 'TreeUtils.pas',
  TreeFillThrd in 'TreeFillThrd.pas',
  DMUnit in 'DMUnit.pas' {DM: TDataModule};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TDM, DM);  
  Application.CreateForm(TfrmMain, frmMain);
  Application.Run;
end.
sutao 4599 2004/5/5 8:03:29
把整个单元内容都贴出来吧,这样看得清楚些
谢谢!!!!
kwbin 4550 2004/5/2 18:23:03
你打开文件就可以看见,这是一个自定义的结构体!
amao3273 4547 2004/5/2 15:52:53
谢啦!我的毕设就在不知不觉中做完啦!我一直在找这段代码,就是没找到 !现在好啦!   谢谢啦!KWBIN 谢谢你帮我把毕设做完!哈哈!
等我做完啦 ! 我就把我毕设的代码公布一下!最好连毕业论文一起发布!免得 学弟学妹们跟我一样  在毕设上浪费时间!
sutao 4517 2004/4/30 16:12:35
KWBIN,PNodeData类型是什么类型??
需要引用哪个单元?
第一页 上一页 下一页 最后页 有 39 条纪录 共2页 1 - 20
 用户名:
 密 码:
自动登陆(30天有效)
 
  DELPHI盒子版权所有 技术支持:深圳市麟瑞科技有限公司 1999-2024 V4.01 粤ICP备10103342号-1 更新RSS列表