关于改变treeview 某些节点文本颜色的问题~~~帮帮忙
在加载二级节点时,从数据库中查询用户名,想能实现这样的功能,在查询用户名的同时判断该用户是否为销户状态,如果是,则将该节点的颜色设为红色,以下是加载二级节点代码:
if treeview1.Selected.HasChildren then//如果当前选中的节点有子节点,则不再加载
abort
else
begin
while not ado_add.Eof do
begin
node_bill:=treeview1.Items.AddChild(treeview1.Selected,ado_add.fieldbyname('khmc').AsString);
if ado_add.FieldByName('xiaohu').AsBoolean=true then
xiaohu_flag:=true;
ado_add.Next;
end;
end;
然后在 customerdrawitem 事件中进行判断:
if xiaohu_flag=true then
treeview1.canvas.font.color:=clred;
这样一来所有的节点都变成了红色,如果用node.level:=clred 则所有的二级节点都变成红色,我只要符合条件的用户才将它的颜色改变,有没有什么方法可以做到啊?在网上找了很多都没达到效果,郁闷中~~~
问题点数:50、回复次数:54Top
1 楼do2008(aiGooo·闲来吹吹牛,不亦乐乎)回复于 2006-11-21 10:53:36 得分 5
我觉得可以在树结点前显示不同的图标,来表示是否销户状态比较好,
设计node_bill的imageindex即可Top
2 楼CloneCenter(复制中心)回复于 2006-11-21 11:13:15 得分 0
CustomerDraw的代码应该没有问题啊。Top
3 楼mdejtod(稻草人)回复于 2006-11-21 11:13:34 得分 0
哦,这样也可以,不过是不是不能改变单个节点的文本颜色啊?Top
4 楼mdejtod(稻草人)回复于 2006-11-21 11:14:52 得分 0
发现只能改变所有节点的颜色,而不能改变单个节点的啊~Top
5 楼sanmaotuo(老冯)回复于 2006-11-21 11:18:12 得分 45
你的语句是没有问题的, 但你的问题出在 if xiaohu_flag=true then
建议你这样改改看:
TNodeData = paceked record
xiaohu_flag: Boolean;
......其他信息
end;
PTNodeData = ^TNodedata;
所有的节点的Data都是此记录类型;
将下面的语句更改:
var
NodeData = PTNodeData;
begin
......
if ado_add.FieldByName('xiaohu').AsBoolean=true then
xiaohu_flag:=true;
更改为
.....
if ado_add.FieldByName('xiaohu').AsBoolean=true then
NodeData.xiaohu_flag:=true;
else
NodeData.xiaohu_flag:=False;
..............
if xiaohu_flag=true then
treeview1.canvas.font.color:=clred;
改为
..........
if PTNodeData(Node.Data).xiaohu_flag=true then
treeview1.canvas.font.color:=clred;
Top
6 楼sanmaotuo(老冯)回复于 2006-11-21 11:19:46 得分 0
漏了一点,在生成节点时还要加上
。。。
Node.Data = @NodeData;Top
7 楼sanmaotuo(老冯)回复于 2006-11-21 11:20:15 得分 0
测试了一下,完全没有问题。Top
8 楼mdejtod(稻草人)回复于 2006-11-21 11:38:57 得分 0
太感谢楼上的了,我先试下~
Top
9 楼mdejtod(稻草人)回复于 2006-11-21 11:47:38 得分 0
PTNodeData = ^TNodedata; //指针?
Node.Data = @NodeData; //这两句还不太明白是什么作用?
if PTNodeData(Node.Data).xiaohu_flag=true then //这边会有地址引用错误,窗体一显示时就会执行这边的代码Top
10 楼sanmaotuo(老冯)回复于 2006-11-21 12:01:51 得分 0
给你一个测试代码,还有什么问题欢迎随时提出(这段代码是偶数节点的字体颜色为红色)
TNodeData = packed record
xiaohu_flag: Boolean;
end;
PTNodeData = ^TNodedata;
TForm1 = class(TForm)
TreeView1: TTreeView;
ImageList1: TImageList;
Button1: TButton;
procedure TreeView1CustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if PTNodeData(Node.Data).xiaohu_flag then
Treeview1.Canvas.Font.Color := clred;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Idx: Integer;
NodeData: array [0..1000] of PTNodeData;
Node: TTreeNode;
begin
for Idx := 0 to 10 do
begin
New(NodeData[Idx]);
Node := Treeview1.Items.AddChild(nil, '');
if Idx mod 2 = 0 then
NodeData[Idx].xiaohu_flag := True
else
NodeData[Idx].xiaohu_flag := False;
Node.Data := NodeData[Idx];
Node.Text := 'Node'+IntToStr(Idx);
Node.ImageIndex := 0;
end;
end;Top
11 楼mdejtod(稻草人)回复于 2006-11-21 12:16:10 得分 0
晕了,还是地址引用错误:
我的代码:(ondbclick) treeview1
Node.Data := @NodeData;
if treeview1.Selected.HasChildren then //如果当前选中的节点有子节点,则不再加载
abort
else
begin
while not ado_add.Eof do
begin
node_bill:=treeview1.Items.AddChild(treeview1.Selected,ado_add.fieldbyname('khmc').AsString);
if ado_add.FieldByName('xiaohu').AsBoolean=true then
NodeData.xiaohu_flag:=true
else
NodeData.xiaohu_flag:=False;
ado_add.Next;
end;
end;
后面的判断代码是一样的,可就是地址引用出错~~~不懂哪错了啊~
还是这两句不懂什么作用~~~
PTNodeData = ^TNodedata; //指针?
Node.Data = @NodeData; //这两句还不太明白是什么作用?
麻烦你了`~~~~
Top
12 楼sanmaotuo(老冯)回复于 2006-11-21 12:31:51 得分 0
全心全意为人民服务。呵呵呵呵
procedure TForm1.TreeView1Click(Sender: TObject);
var
Idx: Integer;
NodeData: array [0..1000] of PTNodeData;
Node_Bill: TTreeNode;
begin
if treeview1.Selected.HasChildren then //如果当前选中的节点有子节点,则不再加载
abort
else
begin
for Idx := 0 to 10 do
begin
New(NodeData[Idx]);
node_bill:=treeview1.Items.AddChild(treeview1.Selected, '');
if Idx mod 2 = 0 then
NodeData[Idx].xiaohu_flag:=true
else
NodeData[Idx].xiaohu_flag:=False;
Node_Bill.Data := NodeData[Idx];
Node_Bill.Text := 'Node'+IntToStr(Idx);
Node_Bill.ImageIndex := 0;
end;
end;
end;Top
13 楼sanmaotuo(老冯)回复于 2006-11-21 12:34:20 得分 0
去看看效果吧, 不过你应该在加上一条就是当Node的LEVEL判断,否则它会无限LEVEL的加节点Top
14 楼mdejtod(稻草人)回复于 2006-11-21 13:59:54 得分 0
晕哪,还是那个错误~~~
procedure TE_khzl_changeF.TreeView1CustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if PTNodeData(Node.Data).xiaohu_flag then
Treeview1.Canvas.Font.Color := clred;
end;
这段代码怎么在窗体一创建时就会执行的啊?Top
15 楼do2008(aiGooo·闲来吹吹牛,不亦乐乎)回复于 2006-11-21 14:09:20 得分 0
顶sanmaotuo(老冯) ~~~
楼上说的,>>这段代码怎么在窗体一创建时就会执行的啊?
原因可能是,你的treeview,在设计时就在添加了一些结点,对吧,
这样的话,窗体在create时,会在创建treeview时,就会执行CustomDrawItem事件,
因此,可按你上边的代码改一下;
procedure TE_khzl_changeF.TreeView1CustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if Node.HasChildren then //添加这个判断
exit;
if PTNodeData(Node.Data).xiaohu_flag then
Treeview1.Canvas.Font.Color := clred;
end;
嘿嘿,我乱猜的~~~
Top
16 楼do2008(aiGooo·闲来吹吹牛,不亦乐乎)回复于 2006-11-21 14:12:02 得分 0
楼上好像也不行,如果,来不及添加二级结点,还是会出错,
procedure TE_khzl_changeF.TreeView1CustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if (Node.level =0) then //这样判断试试,反正一级结点就退出
exit;
if PTNodeData(Node.Data).xiaohu_flag then
Treeview1.Canvas.Font.Color := clred;
end;Top
17 楼sanmaotuo(老冯)回复于 2006-11-21 14:15:50 得分 0
你们的通通的不行,照我的葫芦画画你的瓢看看吧,同志们。Top
18 楼sanmaotuo(老冯)回复于 2006-11-21 14:17:33 得分 0
在加入一级节点是就要把Node.data := PTNodeData, 否则肯定稀里哗啦啦啦。。。我在第一段就已经说明了啊,同志们。呵呵呵呵Top
19 楼do2008(aiGooo·闲来吹吹牛,不亦乐乎)回复于 2006-11-21 14:20:21 得分 0
哈哈哈~~~~~LZ已经稀里哗啦啦啦乐~~~Top
20 楼mdejtod(稻草人)回复于 2006-11-21 14:43:04 得分 0
呵,谢谢两位,我正烦着呢~我在窗体显示时加载了一级节点,双击时加载二级节点,反正到了那边就会出错,我也试着用 do2008 的方法进行判断,如果没有加载二级节点时就退出,窗体显示时没错,可是当双击时还是会有那个错误~~~~~~我的一级节点是在窗体显示时加载的
Node.data := PTNodeData; 这个是写在加载一级节点的地方么?会有错误~~
[Error] E_khzl_change.pas(271): '(' expected but ';' foundTop
21 楼sanmaotuo(老冯)回复于 2006-11-21 15:04:16 得分 0
好累哦。你先抛开你的数据库,找我的测试代码原封不动的测试看看。Top
22 楼mdejtod(稻草人)回复于 2006-11-21 15:07:39 得分 0
呵,~~太感谢你了,我另写一个试试看Top
23 楼mdejtod(稻草人)回复于 2006-11-21 15:29:35 得分 0
我测试过了你的啊,如果不加载两级节点,只加载一级节点的话没问题(按钮),然后我在窗体显示时加载一级节点,在双击事件里加载二级节点后就会有问题了,这要怎么改啊?
----------------------------------------------
在加入一级节点是就要把Node.data := PTNodeData,
----------------------------------------------
可是这个写在加载一级节点时会出错.
真是太麻烦你了~呵~Top
24 楼sanmaotuo(老冯)回复于 2006-11-21 15:34:15 得分 0
无语了。世界需要热心肠
type
TNodeData = packed record
xiaohu_flag: Boolean;
end;
PTNodeData = ^TNodedata;
TForm1 = class(TForm)
TreeView1: TTreeView;
ImageList1: TImageList;
Button1: TButton;
procedure TreeView1CustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
procedure Button1Click(Sender: TObject);
procedure TreeView1Click(Sender: TObject);
private
{ Private declarations }
public
end;
var
Form1: TForm1;
implementation
uses
Clipbrd;
{$R *.dfm}
procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if PTNodeData(Node.Data).xiaohu_flag then
Treeview1.Canvas.Font.Color := clred;
end;
procedure TForm1.Button1Click(Sender: TObject); //增加一级节点
var
Idx: Integer;
NodeData: array [0..1000] of PTNodeData;
Node: TTreeNode;
begin
for Idx := 0 to 10 do
begin
New(NodeData[Idx]);
Node := Treeview1.Items.AddChild(nil, '');
if Idx mod 2 = 0 then
NodeData[Idx].xiaohu_flag := True
else
NodeData[Idx].xiaohu_flag := False;
Node.Data := NodeData[Idx];
Node.Text := 'Node'+IntToStr(Idx);
Node.ImageIndex := 0;
end;
end;
procedure TForm1.TreeView1Click(Sender: TObject); //增加二级节点
var
Idx: Integer;
NodeData: array [0..1000] of PTNodeData;
Node_Bill: TTreeNode;
begin
if treeview1.Selected.HasChildren then
abort
else
begin
for Idx := 0 to 10 do
begin
New(NodeData[Idx]);
node_bill:=treeview1.Items.AddChild(treeview1.Selected, '');
if Idx mod 2 = 0 then
NodeData[Idx].xiaohu_flag:=true
else
NodeData[Idx].xiaohu_flag:=False;
Node_Bill.Data := NodeData[Idx];
Node_Bill.Text := 'Node'+IntToStr(Idx);
Node_Bill.ImageIndex := 0;
end;
end;
end;Top
25 楼sanmaotuo(老冯)回复于 2006-11-21 15:35:52 得分 0
在Click最前面加上
if Treeview1.Selected <> nil thenTop
26 楼mdejtod(稻草人)回复于 2006-11-21 15:54:37 得分 0
问题解决了,晕啊,New(NodeData[Idx]);这个只能在加载一级节点时写,加载二级节点时不能写
New(NodeData[Idx]);你两次加载都写了,我测试时好像不行哦~Top
27 楼sanmaotuo(老冯)回复于 2006-11-21 15:57:46 得分 0
呵呵。恭喜恭喜。共同学习,共同进步!Top
28 楼mdejtod(稻草人)回复于 2006-11-21 16:01:52 得分 0
晕哪,我搞了两个小时了~可是还有问题啊,第一次双击打开二级节点时没问题,如果再点一下其它的节点,那它的颜色马上就会变掉,是不是跟我的树的onchange事件有关啊?这里我只是查找相应的用户记录出来的~Top
29 楼sanmaotuo(老冯)回复于 2006-11-21 16:07:22 得分 0
你在ONChange写了些什么东东?Top
30 楼mdejtod(稻草人)回复于 2006-11-21 16:09:49 得分 0
不关onchange里面的事了,我把里面的代码都去掉了还是一样的,如果再次点击到那个改变了颜色的节点,颜色就会变为原来的,再次展开一级节点也是一样的颜色会变掉~~~~Top
31 楼sanmaotuo(老冯)回复于 2006-11-21 16:13:09 得分 0
你要老冯的命啊?干脆我帮你全部写完算了。 你的一级节点是什么内容?Top
32 楼mdejtod(稻草人)回复于 2006-11-21 16:17:14 得分 0
呵,不敢啊,我觉得奇怪啊,我另外写的一个都不会这样的,真晕~一级节点是区域,二级节点是用户名,我把这两个都给你看下:
窗体的 onshow 事件:
ado_add.SQL.Clear;
ado_add.SQL.Text:='select distinct pqmc from pqzl';
ado_add.Open;
for i:=0 to ado_add.RecordCount-1 do
begin
New(NodeData[i]);
dbcombobox2.Items.Add(ado_add.fieldbyname('pqmc').AsString);
node:=treeview1.Items.Add(nil,ado_add.fieldbyname('pqmc').AsString);
ado_add.Next;
end;
树的 ondbclick事件:
if treeview1.Selected.HasChildren then //如果当前选中的节点有子节点,则不再加载
abort
else
begin
for idx:=0 to ado_add.RecordCount-1 do
begin
node:=treeview1.Items.AddChild(treeview1.Selected,ado_add.fieldbyname('khmc').AsString);
if ado_add.FieldByName('xiaohu').AsBoolean=true then
NodeData[Idx].xiaohu_flag :=true
else
NodeData[Idx].xiaohu_flag :=False;
Node.Data := NodeData[Idx];
ado_add.Next;
end;
end;
你帮我看下哪里有问题-_-~~Top
33 楼sanmaotuo(老冯)回复于 2006-11-21 16:25:40 得分 0
你在哪里定义的NodeData??估计是这个问题啊Top
34 楼mdejtod(稻草人)回复于 2006-11-21 16:27:14 得分 0
应该是加载一级节点时有问题了,改成用按钮来加载就可以,真晕~Top
35 楼mdejtod(稻草人)回复于 2006-11-21 16:30:02 得分 0
在public处啊,可是另一个测试程序也是定义在那边的,都没问题~Top
36 楼sanmaotuo(老冯)回复于 2006-11-21 16:31:23 得分 0
呵呵, 你太粗心了啊: 你看看你在ONSHOW中没有给Node.data赋值啊。
node:=treeview1.Items.Add(nil,ado_add.fieldbyname('pqmc').AsString);
加
......
nodedata[Idx].xiaohu_flag := False;
Node.Data := NodeData[Idx];
......
ado_add.Next;Top
37 楼sanmaotuo(老冯)回复于 2006-11-21 16:32:20 得分 0
怎么能够定义在PUBLIC呢》?Node.data 是Pointer啊!!同志Top
38 楼mdejtod(稻草人)回复于 2006-11-21 16:52:32 得分 0
晕~在加载二级节点时添加一句就好了:New(NodeData[idx]);
可是怎么测试程序都不要这样写却可以达到效果的啊,还有哦,再问你一下,nodedata要定义在哪里呀?这是测试程序:
procedure TForm1.Button2Click(Sender: TObject);//一级
var
i:integer;
begin
for i:=0 to 20 do
begin
New(NodeData[i]);
node:=treeview1.Items.Add(nil,'1221');
end;
end;
procedure TForm1.TreeView1DblClick(Sender: TObject);//二级
var
Idx: Integer;
begin
if treeview1.Selected.HasChildren then
abort
else
begin
for Idx := 0 to 10 do
begin
Node := Treeview1.Items.AddChild(treeview1.Selected,'123' );
if Idx mod 2 = 0 then
NodeData[Idx].xiaohu_flag := True
else
NodeData[Idx].xiaohu_flag := False;
Node.Data := NodeData[Idx];
end;
end;
end;
Top
39 楼sanmaotuo(老冯)回复于 2006-11-21 16:56:35 得分 0
NODE和nodedata的作用域一定只能在某个方法内。Top
40 楼sanmaotuo(老冯)回复于 2006-11-21 16:58:34 得分 0
不论哪一级他的NODE的Data都要赋值。 累啊累啊。冒昧问一下,您是哪里的?Top
41 楼mdejtod(稻草人)回复于 2006-11-21 17:06:20 得分 0
程序不会引用其它地方的同名的指针对象(同名)?我看你在两个方法内都这样定义了:
Idx: Integer;
NodeData: array [0..1000] of PTNodeData;
Node_Bill: TTreeNode;
如果说NodeData只能在一个作用域内,那其它两个变量(idx,node_bill),可是定义在public处的吧?Top
42 楼sanmaotuo(老冯)回复于 2006-11-21 17:13:24 得分 0
其它两个变量(idx,node_bill), 同NodeData一样的地方定义。Top
43 楼mdejtod(稻草人)回复于 2006-11-21 17:13:47 得分 0
呵,真是太谢谢你了,我本来都快不想搞了,你真热心,我现在在广东啊,你呢?嘿嘿,以后还要问你的哦~~我用这才半年不到啊,都是一个人自学,哎,~~难啊~~Top
44 楼sanmaotuo(老冯)回复于 2006-11-21 17:17:22 得分 0
我是广州的。现在成都Top
45 楼sanmaotuo(老冯)回复于 2006-11-21 17:17:53 得分 0
没关系,有什么问题尽管问。Top
46 楼mdejtod(稻草人)回复于 2006-11-21 17:19:57 得分 0
最后再问你一个,呵呵,其实我不太懂这些啊,
TNodeData = packed record //定义一个记录类型
xiaohu_flag: Boolean; //记录中的变量
end;
PTNodeData=^TNodedata; //这个是表示什么意思,指针吗?
NodeData: array [0..1000] of PTNodeData; //nodedata与ptnodedata是什么关系,
New(NodeData[idx]); //这个又是什么呢,
Node_bill.Data := NodeData[Idx]; //node_bill.data表示的是什么啊?
NodeData[Idx].xiaohu_flag //指针,数组都快晕了~
谢谢你啊,只能说谢谢你了,~~~~~!!!!Top
47 楼sanmaotuo(老冯)回复于 2006-11-21 17:26:52 得分 0
TNodeData是记录, PTNodeData=^TNodedata是记录指针,
NodeData: array [0..1000] of PTNodeData;指针数组
Node.Data是无类型指针 ,
New(NodeData[idx]) 初始化指针(创建一个新的动态变量并且把指针指向它)
Node_bill.Data := NodeData[Idx]; 指针复制
NodeData[Idx].xiaohu_flag 读取记录指针指向的内存空间中某个字段数据Top
48 楼zczb(zczb)回复于 2006-11-21 17:36:17 得分 0
建议lz把分全给老冯Top
49 楼mdejtod(稻草人)回复于 2006-11-21 19:07:47 得分 0
嗯,运行过程知道了,可是还不是很懂整个的原理,为什么要采用这种指针数组~~~~-_-~~~
PTNodeData(Node.Data). 这样是表示什么呢?
Top
50 楼sanmaotuo(老冯)回复于 2006-11-21 19:27:42 得分 0
呵呵。挺刻苦的啊。
PTNodeData(Node.Data)把无类型指针转换成PTNodeData类型指针。
数组是为了保存多个节点数据指针Top
51 楼mdejtod(稻草人)回复于 2006-11-21 19:38:35 得分 0
嗯,呵呵,跟了半天了,刚刚我看了下指针数组跟数组指针的区别.
那可不可以不用无类型指针node.data,这个应该是相当于一个中间变量一样的吧,这个是在任何一个方法里面都可以用的吗,无须定义? 直接用这样 nodedata[idx].xiaohu_flag 来判断可不可以? (好像不行,这个指针数组是只能在一个作用域内的)老大,你QQ多少啊?以后还会向你请教的呢~Top
52 楼sanmaotuo(老冯)回复于 2006-11-21 19:44:07 得分 0
呵呵。今天先讲到这里吧。以后慢慢交流
5040071Top
53 楼sanmaotuo(老冯)回复于 2006-11-21 19:45:15 得分 0
请散分吧。呵呵呵呵Top
54 楼mdejtod(稻草人)回复于 2006-11-21 19:49:44 得分 0
呵,会的~谢谢啦~Top




