Форум: "Базы";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
ВнизГоспода, как можно "привязать" к TTreeNode номер записи Найти похожие ветки
← →
mmms (2005-07-11 08:52) [0]Т.е. предположим есть ветка в TTreeView "Продукты", от нее дочерние ноды "Колбаса", "Хлеб" и т.п. Нужно, чтобы юзер кликнул на "Хлеб", узнать, какой ID записи у "Хлеб", TTreeView заполняю записями из БД. Можно ли TTreeNode заполнить кроме Значениями ещё и скрытые параметры у каждого значения, например как Tag у многих компанетов, и потом, при клике на строку, определять этот параметр, а там всего цифровой код товара (по нему далее вся работа и идет).
Или, как вариант, по LIKE определять ID выбранной строки, но это лишняя нагрузка на БД, т.к. даже скольжение по TTreeView создаст множество запросов к серверу... хотя конечно, ID методом LIKE, по названию, можно не постоянно определять при скольжении, а например при двойном клике не этом товаре.
Т.е. вопрос, можно ли как то рядом с позицией в TTreeView "вбивать" ее код.
← →
k2 © (2005-07-11 08:54) [1]node.data
← →
mmms (2005-07-11 09:00) [2]Можно ли данного примера показать, заполняюю этой процедурой..
{ **** UBPFD *********** by delphibase.endimus.com ****
>> Процедура заполнения компонента TTreeView данными из TDataSet-совместимой выборки
Процедура заполнения компонента TTreeView данными из TDataSet-совместимой
выборки типа: idNode int, idParentNode int, cNodeName varchar, ...
Важно: корневой узел дерева должен быть первой записью выборки.
Зависимости: Windows, SysUtils, DB, ComCtrls
Автор: Delirium, Master_BRAIN@beep.ru, ICQ:118395746, Москва
Copyright: Master BRAIN (Delirium)
Дата: 18 октября 2002 г.
***************************************************** }
procedure FillTree(Tree: TTreeView; Query: TDataSet; idNode, idParent,
cNodeName: string);
var
i: integer;
begin
// Корневой узел, должен быть первым в выборке Query
Query.First;
Tree.Items.Clear;
Tree.Items.AddObject(nil, Query.FieldByName(cNodeName).AsString,
Pointer(Query.FieldByName(idNode).asInteger));
Query.Next;
while not Query.Eof do
begin
i := 0;
while i < Tree.Items.Count do
if Tree.Items.Item[i].Data = Pointer(Query.FieldByName(idParent).asInteger)
then
begin
Tree.Items.AddChildObject(Tree.Items.Item[i],
Query.FieldByName(cNodeName).AsString,
Pointer(Query.FieldByName(idNode).asInteger));
break;
end
else
Inc(i);
Query.Next;
end;
end;
← →
k2 © (2005-07-11 09:15) [3]вместо idParent писать при заполнении дерева в Data букмарку, например:
Tree.Items.AddObject(nil, Query.FieldByName(cNodeName).AsString, Query.GetBookmark);
при клике по нодам дерева переходить в датасете на соответствующую запись
← →
evvcom © (2005-07-11 09:23) [4]А что, запрос не может возвратить уже отсортированное нужным образом дерево, чтобы не сканить после каждого Next весь TreeView? При большом количестве записей в этом месте наступят бАльшие тормоза. База-то какая?
← →
mmms (2005-07-11 09:30) [5]
k2 © (11.07.05 09:15)
Интересное предложение, с GetBookmark попробовал, может что делаю не так (никогда до этого не сталкивался), перестала строится структура с ним, т.е. без Pointer(Query..[4] evvcom © (11.07.05 09:23)
Да, таблица может быть и 1000 позиций, может и 10000 быть. Поэтому захотелось сделать древовидное меню, для быстроты выбора товара по его типу. Процедура от Delirium идеально подходит, вот только как "получить" значение ID товара не знаю.
← →
Anatoly Podgoretsky © (2005-07-11 09:39) [6]Третий параметр AddChildObject - это пользовательские данные, если у тебя ID = Integer, то можешь его прямо писать через приведение к Pointer и обратно.
← →
ANB © (2005-07-11 09:42) [7]
> mmms (11.07.05 09:30) [5]
- есть предложение. Имхо. Сами товары храни в плоской таблице с привязкой к древовидной с группами товаров. Тогда легко переключать - дерево / алфавитный список (не всем пользователям и не во всех режимах работы нравится работать с деревом) и инфы в дереве можно по минимуму хранить, а товары группы можно доставать отдельным запросом с любыми полями. И тормозить при закачке сильно не будет, так как групп сильно много не бывает. Кстати, в оракле есть CONNECT BY, который сам дерево строит.
← →
evvcom © (2005-07-11 09:50) [8]
> как "получить" значение ID товара не знаю
В примере Query.FieldByName(idNode).asInteger - это и есть "получение ID", в чем проблема?
> может быть и 1000 позиций, может и 10000 быть
Удивляет игнорирование авторами уточняющих вопросов! 10000 - это довольно много. Даже при одноразовом пробеге по такому количеству записей для построения TreeView будет заметна пауза. А уж при
> while not Query.Eof do
> begin
> i := 0;
> while i < Tree.Items.Count do
эта пауза превратится в "смерть"!
Во-первых, надо подумать о сокращении количества выбираемых данных.
Во-вторых, отсортировать возвращаемый набор средствами SQL. Как? Для этого мы должны услышать ответ на вопрос
> База-то какая?
Который был проигнорирован.
← →
evvcom © (2005-07-11 09:54) [9]
> Кстати, в оракле есть CONNECT BY
Вот и я к тому же. Только фиг знает какой сервак у автора, а то может у него вовсе базы dBase или Paradox? А мы тут надрывайся ему, советуй из чего космический корабль построить, когда у него инструментов на велосипед недостаточно.
← →
mmms (2005-07-11 10:18) [10]
evvcom © (11.07.05 09:54)
прошу прощения, MSSQL2000, в принципе понятно, лучше старым дедовским способом, связанные таблицы, вид-товар. Сортировать... под данную процедуру это сложно, если надо что бы родители были всегда вверху.
← →
mmms (2005-07-11 10:20) [11]
rowid idnode idchildnode caption
1 1 1 Магазин
2 2 1 Продукты
3 30 1 Электроника
4 40 1 Бытовая химия
5 50 2 Фрукты
6 51 2 Овощи
7 52 2 Молочные
8 1 52 Молоко
9 1 52 Кефир
10 1 52 Сгущ. молоко
11 1 52 Ряженка
12 1 52 Сыр
13 1 52 Творог
14 1 51 Картофель
15 1 51 Морковка
16 1 51 Огурцы
17 1 50 Яблоки
18 1 50 Груша
19 1 50 Слива
20 100 30 DVD-плеер
21 101 30 Телевизор
22 102 30 Видеомагнитофон
23 103 30 Музыкальные центры
24 1 100 BBK 911 S
25 1 100 BBK 911
26 1 100 BBK 912 S
27 1 100 BBK 912
28 1 101 Sony 21""
29 1 101 Sony 25""
30 1 102 LG 944
31 1 102 LG 945
Как пример, вывод на экран только DVD-плеера...
← →
msguns © (2005-07-11 10:24) [12]>mmms
Дай мыло, вышлю форму-модуль древовидного справочника
← →
mmms (2005-07-11 10:28) [13]
msguns © (11.07.05 10:24)
worldsite2000 @ mail.ru
Заранее благодарю :)
← →
evvcom © (2005-07-11 10:35) [14]1. idchildnode заменить на idparentnode или вообще на idparent
2. НД лучше отсортировать в виде:
id idparent caption level
1 1 Магазин 1
30 1 Электроника 2
...
40 1 Бытовая химия 2
2 1 Продукты 2
50 2 Фрукты 3
1 50 Яблоки 4 ***
1 50 Груша 4 ***
1 50 Слива 4 ***
51 2 Овощи 3
1 51 Картофель 4 ***
1 51 Морковка 4 ***
1 51 Огурцы 4 ***
52 2 Молочные 3
1 52 Молоко 4 ***
1 52 Кефир 4 ***
1 52 Сгущ. молоко 4 ***
1 52 Ряженка 4 ***
1 52 Сыр 4 ***
1 52 Творог 4 ***
3. id должен быть уникальным, поэтому записи помеченные *** имеют неверные id
4. добавить поле level, для более простого анализа на клиенте
5. пример построения дерева для MSSQL давали мастера на этом форуме. Уже не помню кто. Сейчас сделал поиск: не нашел. Привожу тот код:
CREATE FUNCTION TreeFromTable (@Root INT)
RETURNS @T TABLE (ID INT, Owner INT, level INT) AS
BEGIN
DECLARE @level INT
SET @Level=0
INSERT @T SELECT @Root, 0, 0
while exists(SELECT * FROM @T T, Structure S WHERE
T.level=@level and S.Owner=T.ID)
begin
INSERT @T (ID,Owner,Level)
SELECT S.ID, S.Owner, @level+1 from @T T, Structure S WHERE T.level=@level and S.Owner=T.ID
SET @level=@level+1
end
RETURN
END
← →
msguns © (2005-07-11 11:08) [15]Лови. Комментарии в письме.
← →
mmms (2005-07-11 11:18) [16]
msguns © (11.07.05 11:08)
Сергей, пока ничего нет, там пробелы между собачкой, если в них дело, или должно позже подойти, буду ждать, спасибо.evvcom © (11.07.05 10:35)
Так же спасибо за решение, idnode и idchildnode это не ID товара, а указатели для древовидного меню (кстати, рисуется очень хорошо :) ) а вот rowid и есть ID товара, из за нее весь сыр бор.
← →
msguns © (2005-07-11 11:31) [17]>mmms (11.07.05 11:18) [16]
БД там интербэйз и "ветки" вытаскиваются хранимкой. Уже отсортированной по узлам.
Основа же в том, что записи БД помещаются в объекты, указатели на которых и "засовываются" в тривью. Весь справочник не считывается (для этого есть режим линейного просмотра), т.к. одномоментно надо показывать лишь одну (текущую в тривью) группу/подгруппу. Т.е. юзер кликает на узле тривью и в гриде отображается содержимое его листьев, а также листьев подчиненных узлов.
← →
msguns © (2005-07-11 11:33) [18]>msguns © (11.07.05 11:31) [17]
>Т.е. юзер кликает на узле тривью и в гриде отображается содержимое его листьев, а также листьев подчиненных узлов.
Отображаются только листья текущего узла. Извиняюсь за путаницу - проект старый, уже подзабыл ;)
← →
evvcom © (2005-07-11 11:36) [19]
> а вот rowid и есть ID товара
Тогда idparent должен ссылаться на этот rowid. А вообще смысл rowid несколько иной, поэтому, чтобы избежать кривотолков в будущем, советую все же row из этого названия убрать.
← →
mmms (2005-07-11 11:37) [20]
[18] msguns © (11.07.05 11:33)
Да ничего, хорошо, посмотрю как у других это делается :)
← →
Ega23 © (2005-07-11 11:39) [21]
unit uKdrDBTreeView;
interface
uses Windows, SysUtils, Classes, comctrls, stdctrls, db, graphics, controls,
Dialogs, contnrs;
Type
TCustomKdrDBTreeView=class;
TKdrDBTreeViewItemIdent = class(TObject)
private
FParentKeyFieldValue: Variant;
FKeyFieldValue: Variant;
FDisplayFieldValue: String;
FImageFieldValue: Integer;
FNode: TTreeNode;
public
property KeyFieldValue:Variant Read FKeyFieldValue Write FKeyFieldValue;
property ParentKeyFieldValue:Variant Read FParentKeyFieldValue Write FParentKeyFieldValue;
property DisplayFieldValue:String Read FDisplayFieldValue Write FDisplayFieldValue;
property ImageFieldValue:Integer Read FImageFieldValue Write FImageFieldValue;
property Node:TTreeNode Read FNode Write FNode;
end;
TTreeDataLink = class(TDataLink)
private
FTree: TCustomKdrDBTreeView;
FMinParent: Integer;
FMinValue: Integer;
public
constructor Create(ATree:TCustomKdrDBTreeView);
procedure DataSetChanged; override;
procedure ActiveChanged; override;
property MinParent:Integer Read FMinParent Write FMinParent;
property MinValue:Integer Read FMinValue Write FMinValue;
end;
TCustomKdrDBTreeView = class(TCustomTreeView)
private
FDataLink: TTreeDataLink;
FTreeItems:TObjectList;
FKeyField: String;
FDisplayField: String;
FParentField: String;
FDataSource: TDataSource;
Inh_TVChange: TTVChangedEvent;
procedure SetFDataSource(const Value: TDataSource);
protected
function LocateByNode(Node:TTreeNode):Boolean;
procedure TVChange(Sender: TObject; Node: TTreeNode);
procedure AddAllNodes(ParentID: Integer; ParentNode:TTreeNode);
function SetSelectedNode(const Value:Variant):TTreeNode;
property DataSource:TDataSource Read FDataSource Write SetFDataSource;
property DisplayField:String Read FDisplayField Write FDisplayField;
property KeyField:String Read FKeyField Write FKeyField;
property ParentField:String Read FParentField Write FParentField;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Clear;
procedure DataChanged;
procedure ActiveChanged;
function AddItem:Integer;
end;
TKdrDBTreeView = class (TCustomKdrDBTreeView)
published
property DataSource;
property DisplayField;
property KeyField;
property ParentField;
end;
implementation
{ TTreeDataLink }
//*****************************************************************************
procedure TTreeDataLink.ActiveChanged;
var
i:Integer;
begin
inherited;
FTree.Clear;
if (DataSet.Active) and (FTree<>nil) and (dsBrowse in [DataSet.State]) then
begin
BufferCount:=DataSet.RecordCount;
i:=0;
ActiveRecord:=i;
MinParent:=DataSet.FieldByName(FTree.KeyField).Value;
MinValue:=DataSet.FieldByName(FTree.ParentField).Value;
While (i<BufferCount) do
begin
FTree.AddItem;
With DataSet do
begin
if MinValue>FieldByName(FTree.KeyField).AsInteger then
MinValue:=FieldByName(FTree.KeyField).AsInteger;
if MinParent>FieldByName(FTree.ParentField).AsInteger then
MinParent:=FieldByName(FTree.ParentField).AsInteger;
end;
Inc(i);
ActiveRecord:=i;
end;
FTree.ActiveChanged;
ActiveRecord:=0;
end;
end;
//*****************************************************************************
constructor TTreeDataLink.Create(ATree: TCustomKdrDBTreeView);
begin
inherited Create;
FTree:=ATree;
VisualControl:=True;
end;
← →
Ega23 © (2005-07-11 11:39) [22]
//*****************************************************************************
procedure TTreeDataLink.DataSetChanged;
begin
inherited;
if (DataSet.Active) and (FTree<>nil) and (dsBrowse in [DataSet.State]) then
FTree.DataChanged;
end;
//*****************************************************************************
{ TKdrDBTreeView }
procedure TCustomKdrDBTreeView.ActiveChanged;
begin
Items.BeginUpdate;
AddAllNodes(FDataLink.MinParent, nil);
Items.EndUpdate;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.AddAllNodes(ParentID: Integer;
ParentNode: TTreeNode);
var
k:Integer;
CurrNode:TTreeNode;
begin
for k:=0 to FTreeItems.Count-1 do
begin
With TKdrDBTreeViewItemIdent(FTreeItems.Items[k]) do
begin
if (Node<>nil) or (ParentKeyFieldValue<>ParentID) then Continue;
if ParentNode=nil then
CurrNode:=Items.Add(nil, DisplayFieldValue)
else
CurrNode:=Items.AddChild(ParentNode, DisplayFieldValue);
CurrNode.ImageIndex:=ImageFieldValue;
CurrNode.SelectedIndex:=ImageFieldValue;
Node:=CurrNode;
CurrNode.Data:=FTreeItems.Items[k];
AddAllNodes(KeyFieldValue, CurrNode);
end; // With
end; // for
end;
//*****************************************************************************
function TCustomKdrDBTreeView.AddItem: Integer;
var
i:Integer;
begin
try
i:=FTreeItems.Add(TKdrDBTreeViewItemIdent.Create);
With TKdrDBTreeViewItemIdent(FTreeItems.Items[i]) do
begin
KeyFieldValue:=FDataLink.DataSet.FieldByName(KeyField).Value;
ParentKeyFieldValue:=FDataLink.DataSet.FieldByName(ParentField).Value;
DisplayFieldValue:=FDataLink.DataSet.FieldByName(DisplayField).AsString;
end;
except
Result:=-1;
end;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.Clear;
var
i:Integer;
begin
FTreeItems.Clear;
Items.Clear;
end;
//*****************************************************************************
constructor TCustomKdrDBTreeView.Create(AOwner: TComponent);
begin
inherited;
HideSelection:=False;
FDataLink:=TTreeDataLink.Create(Self);
FTreeItems:=TObjectList.Create(True);
if Assigned(Self.OnChange) then Inh_TVChange:=Self.OnChange;
Self.OnChange:=TVChange;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.DataChanged;
begin
Selected:=SetSelectedNode(FDataLink.DataSet.FieldByName(KeyField).AsInteger);
end;
//*****************************************************************************
destructor TCustomKdrDBTreeView.Destroy;
begin
FTreeItems.Free;
FDataLink.Free;
inherited;
end;
//*****************************************************************************
function TCustomKdrDBTreeView.LocateByNode(Node: TTreeNode): Boolean;
var
i:Integer;
V:Variant;
keyFields:String;
begin
Result:=False;
for i:=0 to FTreeItems.Count-1 do
if TKdrDBTreeViewItemIdent(FTreeItems.Items[i]).Node=Node then
begin
V:=VarArrayCreate([0,1], varVariant);
V[0]:=TKdrDBTreeViewItemIdent(FTreeItems.Items[i]).KeyFieldValue;
V[1]:=TKdrDBTreeViewItemIdent(FTreeItems.Items[i]).ParentKeyFieldValue;
keyFields:=KeyField+";"+ParentField;
Result:=FDataLink.DataSet.Locate(KeyFields,V , []);
end;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.SetFDataSource(const Value: TDataSource);
begin
if (Value<>nil) and (FDataSource<>Value) then
begin
FDataSource := Value;
FDataLink.DataSource:=Value;
end;
end;
//*****************************************************************************
function TCustomKdrDBTreeView.SetSelectedNode(
const Value: Variant): TTreeNode;
var
i:Integer;
begin
Result:=nil;
for i:=0 to FTreeItems.Count-1 do
With TKdrDBTreeViewItemIdent(FTreeItems.Items[i]) do
if KeyFieldValue=Value then
begin
Result:=Node;
Break;
end;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.TVChange(Sender: TObject; Node: TTreeNode);
begin
LocateByNode(Node);
if (@Inh_TVChange<>nil) then Inh_TVChange(Sender, Node);
end;
//*****************************************************************************
end.
← →
Андрей Жук © (2005-07-11 16:20) [23]
{
Формат елементів усіх дерев
mem_id - обовязково. Ідентифікатор елемента
mem_pid - обовязково. Ідентифікатор "батьківського" елемента
is_leaf - обовязково. Ознака, чи є елемент елементом нижнього рівня
outlevel - обовязково. Рівень елемента
mem_order - обовязково. Порядковий номер в структурі
mem_name - обовязково. Назва елемента
mem_desc - обовязково. Описання елемента
mem_type - не обовязково. Тип елемента
}
type
TMyTreeNodes = record
mem_id: integer;
mem_pid: integer;
is_leaf: boolean;
outlevel: integer;
mem_order: integer;
mem_name: string;
mem_desc: string;
mem_type: string;
changing: boolean; // чи змінювалися дані в обєкті
inserting: boolean; //чи є обєкт доданим (без відображення в базі)
ParentNode: TTreeNode;
end;
PTMyTreeNodes = ^TMyTreeNodes;
function GenerateTree(Tree: TTreeView; DataSet: TDataSet): TFunctionResult;
var
FunctionResult: TFunctionResult;
vData: PTMyTreeNodes;
Node, LastNode: TTreeNode;
begin
Result.Successful := false;
// якщо дерево чи датасет не ініціалізовані, зупинити виконання
if not Assigned(Tree) or not Assigned(DataSet) then
begin
Result.MessageOnError := "Programmer error - not initilized objects on creating tree";
Exit;
end;
// якщо датасет не активний, то зупинити виконання
if not DataSet.Active then
begin
Result.MessageOnError := "Programmer error - not activated Dataset";
Exit;
end;
// очистимо дерево, якщо помилка зупинити виконання
try
LockWindowUpdate(Tree.Parent.Handle);
FunctionResult := ClearTree(Tree);
if not FunctionResult.Successful then
begin
Result.MessageOnError := FunctionResult.MessageOnError;
Exit;
end;
// заповнимо дерево
with DataSet do
begin
LastNode := nil;
First;
while not Eof do
begin
New(vData); // створимо елемент
with vData^ do
begin
// заповнюємо його поля
try
mem_id := FindField("mem_id").AsInteger;
mem_pid := FindField("mem_pid").AsInteger;
is_leaf := boolean(FindField("is_leaf").AsInteger);
outlevel := FindField("outlevel").AsInteger;
mem_order := FindField("mem_order").AsInteger;
mem_name := FindField("mem_name").AsString;
mem_desc := FindField("mem_desc").AsString;
if Assigned(FindField("mem_type")) then
mem_type := FindField("mem_type").AsString
else
mem_type := "general";
changing := false;
inserting := false;
except on E: Exception do
begin
Result.MessageOnError := "Programm error - incompatible structure" + #10#13 + "Details: " + E.Message;
Exit;
end;
end;
// якщо це елемент верхнього рівня, то додамо його в корінь
if vData.outlevel = 1 then
begin
Node := Tree.Items.Add(nil, vData^.mem_desc);
vData.ParentNode := nil;
end
// якщо елемент нижчого рівня, то додати як "сина"
else if PTMyTreeNodes(LastNode.Data)^.outlevel < vData.outlevel then
begin
Node := Tree.Items.AddChild(LastNode, vData^.mem_desc);
vData.ParentNode := LastNode;
end
// якщо елемент одного рівня, то додати як "брата"
else if PTMyTreeNodes(LastNode.Data)^.outlevel = vData.outlevel then
begin
Node := Tree.Items.AddChild(LastNode.Parent, vData^.mem_desc);
vData.ParentNode := LastNode.Parent;
end
// якщо елемент вищогого рівня, то знайти "підходящого батька" та додати як "сина"
else if PTMyTreeNodes(LastNode.Data)^.outlevel > vData.outlevel then
begin
while PTMyTreeNodes(LastNode.Data)^.outlevel >= vData.outlevel do
LastNode := LastNode.Parent;
Node := Tree.Items.AddChild(LastNode, vData^.mem_desc);
vData.ParentNode := LastNode.Parent;
end;
// занесення даних до структури
Node.Data := vData;
LastNode := Node;
Next;
end;
end;
end;
Result.Successful := true;
finally
LockWindowUpdate(0);
end;
end;
← →
Ega23 © (2005-07-11 16:27) [24]2 Андрей Жук © (11.07.05 16:20) [23]
Я бы на твоём месте вот сюда// заповнимо дерево
with DataSet do
begin
LastNode := nil;
First;
while not Eof do
ещё DisableControls поставил (в конце - EnableControls).
← →
mmms (2005-07-18 10:24) [25]Приветствую всех!
Снова с TreeView,
Код от mmms (11.07.05 09:00)
Как можно узнать вот это Pointer(Query.FieldByName(idNode).asInteger) значение, например в Showmessage("");, т.е. привести к string.
← →
mmms (2005-07-18 10:25) [26]Делаю так, ошибка:
procedure TForm1.tvClick(Sender: TObject);
begin
Showmessage(PString(tv.Selected.Data)^);
end;
← →
Ega23 © (2005-07-18 10:46) [27]Слушай, может ты сначала какую-нибудь книжку почитаешь? Про типы данных, например? Про указатели? Про классы?
Чтобы вот с таим-вот Showmessage(PString(tv.Selected.Data)^) не позориться?
← →
Anatoly Podgoretsky © (2005-07-18 10:56) [28]Ega23 © (18.07.05 10:46) [27]
Не царское дело!
← →
mmms (2005-07-18 11:26) [29]Послать к книге понятно, проще всего, я понять не могу, как через указатель, прочитать значение. В данном случае это нетипизированный указатель, который может указывать на данные произвольного типа. Видимо не туда "обращаюсь" чтобы прочитать данные...
И 2й вопрос, можно ли запихнуть в коде[2] mmms (11.07.05 09:00)
Data типа String. Я просто туда буду писать 2 строки, вместо теперешноего одного числа. Вопрос в том, что делая это, у меня не происходит "отрисовки меню", т.е. дальше строки
if Tree.Items.Item[i].Data = Pointer(Query.FieldByName(idParent).asString)
Как будто String не сравнивается...
← →
Ega23 © (2005-07-18 11:28) [30]Читай про PChar
← →
evvcom © (2005-07-18 11:35) [31]
> Я просто туда буду писать 2 строки
Это как? В Pointer можно записать только один указатель. Неважно на что: string, char, integer или вообще на мусор. Важно, как этот указатель будешь потом интерпретировать.
> Как будто String не сравнивается
В [2] никаких указателей на string я не увидел, поэтому делать какие-то выводы просто не из чего.
← →
mmms (2005-07-18 13:57) [32]Ega23
Хорошо, почему так ошибку выдает, что я не так пишу? (прошу извинить за такие вопросы)
procedure TForm1.tvClick(Sender: TObject);
begin
Showmessage(PChar(tv.Selected.Data));
end;
evvcom
Ну да, сейчас пишется ссылка на Integer, я хотел вместо этого Integer TStringList хранить, текст типа "fdfg"+#13#10+"fdgfgfg"... и по TStringList делать сравнение в условии, да что то не сравнивается, и в итоге кроме одного итема на Tree больши ничего нет, что и логично. Но это заморочки мои, мне надо всего лишь записать + вытащить число в Data. Был бы Tag, как бы хорошо было :) То что тут код был.. он конечно хорош, но процедура [2] мне очень подходит, осталось только достать Data.
← →
evvcom © (2005-07-18 14:08) [33]
> почему так ошибку выдает
Что за ошибка? Неужели влом написать?
> ... и по TStringList делать сравнение в условии, да что
> то не сравнивается
Ну долго мы в телепатов будем играть? Ну прям Пельш новоиспеченный с игрой "Угадай, мою писанину!"
← →
mmms (2005-07-18 14:31) [34]EAccessViolation
"Access violation at address ..."
← →
Anatoly Podgoretsky © (2005-07-18 14:34) [35]У тебя указатель не верный!
← →
mmms (2005-07-18 14:45) [36]Анатолий, так я понял, я с утра хочу спросить, как верный то написать :(
Showmessage(PChar(tv.Selected.Data));
← →
mmms (2005-07-18 14:45) [37]Удалено модератором
← →
Ega23 © (2005-07-18 14:47) [38]Блин, ты сначала разберисть, что ты в tv.Selected.Data раньше положил. В каком виде?
← →
Anatoly Podgoretsky © (2005-07-18 14:48) [39]mmms (18.07.05 14:45) [36]
Если в tv.Selected.Data ASCIIZ то приведение правильное
← →
mmms (2005-07-18 14:59) [40]Блин, ты сначала разберисть, что ты в tv.Selected.Data раньше положил. В каком виде?
Разобрался.. Ложу Integer, (код [2] mmms (11.07.05 09:00)), как этот интегер считать?
В режиме отладки посмотрел, tv.Items.Item[0].Data=$64,procedure TForm1.tvClick(Sender: TObject);
begin
if tv.Items.Item[0].Data<> nil then
Showmessage(PChar(tv.Items.Item[0].Data)); //=$64
end;
← →
mmms (2005-07-18 14:59) [41]Ну и тут же ошибка.. Access...
← →
evvcom © (2005-07-18 15:07) [42]А что ты хотел увидеть? Ты преобразовываешь $64 к указателю на строку. Естественно? при чтении по адресу $64 ты получаешь AV. Ложить надо туда валидный указатель на строку, чтобы так читать.
← →
Ega23 © (2005-07-18 15:09) [43]2 mmms (18.07.05 14:59) [40]
Разобрался.. Ложу Integer, (код [2] mmms (11.07.05 09:00)), как этот интегер считать?
Чтобы показать Integer в виде строки, воспользуйся функцией IntToStr.
А вообще у тебя полная каша в голове. Тебе надо сначала разобраться и понять, что такое адрес и значение по адресу.
← →
mmms (2005-07-18 15:17) [44]Причем тут каша, я столкнулся с единственным препятствием, может мне теперь и застрелится ещё :) Спрашиваю, если это не сложно, то хотелось бы получить ответ, как прочитать этот Data. На счет ф-и IntToStr, но куда ее тут применить? Ega23, всмотритесь внимательно в код. Data возвращает Pointer а не Integer.
← →
mmms (2005-07-18 15:18) [45]Но там лежит Integer...
← →
Ega23 © (2005-07-18 15:33) [46]Вот смотри:
var
p:PInteger;
i:Integer;
begin
New(p); // Чему сейчас равно значение p? Это может быть что угодно, например $364F5CAD
// Так вот, это - адрес Integer"а
i:=6; //
p^:=i; // Значение ПО АДРЕСУ изменилось, но значение АДРЕСА - нет.
end;
← →
Anatoly Podgoretsky © (2005-07-18 15:37) [47]mmms (18.07.05 15:17) [44]
А что ему еще выдавать, что бы это были универсальные данные? Ты знаешь такой тип?
← →
mmms (2005-07-18 15:54) [48][46] Ega23 © (18.07.05 15:33)
Да, у меня только значения не меняются, и хочется ТОЛЬКО считать это значение.
Так, что ли? :(Showmessage(String(PInt(tv.Items.Item[0].Data)));
Ошибка Access...
Интересно тоже:Showmessage(Pchar(@tv.Items.Item[0].Data));
Выдает букву "D"
Вот только как обратится к памяти, где лежит Data, так и не понял :(
← →
evvcom © (2005-07-18 16:04) [49]Объясни, наконец, что ты хочешь? К ноду привязать стринг, а потом его где-то использовать? Ну так и пиши:
tv.Items[0].Data := Pointer(MyString);
читай:
ShowMessage(string(tv.Items[0].Data));
Только надо быть осторожным. Любое присвоение переменной MyString, после того как она была запомнена в Data, может сделать этот указатель (Data) недействительным, и опять получишь AV при попытке чтения данных по указателю Data.
← →
msguns © (2005-07-18 16:05) [50]>mmms
Ты смотрел то, что я посылал тебе ?
А если смотрел, то не мог не орбратить внимание на это :type
// Описатели объектов справочника
PGR_Info = ^GR_Info; // Группа - узел TreeView
GR_Info = record
ID: integer; // ID группы
IDP: integer; // ID родителя группы
Txt: string; // Отображаемая метка группы
Lev: integer; // Уровень группы в дереве (0 для корневых)
ChQ: integer; // Кол-во непосредственных потомков ("деток")
end;
и это:function TfrbaseSpr.GetGroupsInTreeView: boolean;
// Процедура извлечения информации о группах справочника в список и дерево
var
gline: PGR_Info;
i,j: integer;
begin
result := false;
sttAction.Caption := "Загрузка дерева..";
sttOpStatus.Caption := "";
pnStatus.Update;
// Инициализация TreeView
trvSpr.Items.Clear;
GR_List.Clear;
with quTree do
try
if Active then Close;
Open;
First;
// Цикл по записям НД, полученного из записей справочника запросом со
// след.обязательными условиями:
// - Выбираются только записи групп (поле XXGROUP>"")
// - Записи упорядочены по PID, ID, т.е. "родители" раньше "детей"
// - Поля в НД следуют в след.порядке: IDP, ID, NAME
While not Eof do
begin
NEW(gline);
gline^.ID := Fields[1].AsInteger;
gline^.IDP := Fields[0].AsInteger;
gline^.Txt := Fields[2].AsString;
gline^.Lev := 0; // Уровень по умолчанию = корню
gline^.ChQ := 0; // Кол-во "детишек"
GR_List.Add(gline); // Добавить в список групп
Next;
end;
except
sttOpStatus.Caption := "Ошибка чтения справочника";
end;
quTree.Close;
if GR_List.Count>0 then
// Загрузка из списка в TreeView
for i := 0 to GR_List.Count-1 do // Перебор списка сверху вниз
begin
gline := GR_List.Items[i];
if gline^.IDP=0 then // Узел не входит никуда, добавляем его "в корень" "дерева"
trvSpr.Items.AddObject(nil,gline^.Txt,gline)
else // Узел куда-то входит. Ищем "папашку" в TreeView
for j := 0 to trvSpr.Items.Count-1 do
if PGR_Info(trvSpr.Items[j].Data)^.ID=gline^.IDP then // Нашли !
begin
trvSpr.Items.AddChildObject(trvSpr.Items[j],gline^.Txt,gline); // Добавить как "дитя"
gline^.Lev := PGR_Info(trvSpr.Items[j].Data)^.Lev+1; // Уровень
inc(PGR_Info(trvSpr.Items[j].Data)^.ChQ); // Кол-во "детишек" у "папки"
break;
end;
end;
for i := 0 to trvSpr.Items.Count-1 do
begin // Рисуем рядом с наименованием узла "красивую" иконку
trvSpr.Items[i].ImageIndex := 1;
trvSpr.Items[i].SelectedIndex := 1; // Если false, то при выборке иконка не рисуется ;(
end;
if trvSpr.Items.Count>0 then
begin // Сортируем дерево по наименованиям узлов и первый делаем активным
trvSpr.CustomSort(@CustSortTreeNodes,0);
trvSpr.Selected := trvSpr.Items[0];
end;
sttAction.Caption := "Просмотр";
pnStatus.Update;
end;
Кроме того, у Андрей Жук © (11.07.05 16:20) [23]
схема использования для хранения в дереве данных о записях аналогичная.
И заключается в том, что объявляем объект (record), типизированный указатель на него и добавляем в TTreeView указатель на этот объект. При извлечении информации из "дерева" (св-во Data) используем явное преобразование к нужному типу и корректно работаем с любыми данными объекта.
← →
Ega23 © (2005-07-18 16:07) [51]Вот только как обратится к памяти, где лежит Data, так и не понял :(
(tv.Items.Item[0].Data^)
А что у тебя там лежит - это ты, брат, сам знать должен. Если String, то
ShowMessage(tv.Items.Item[0].Data^),
если Integer, то
ShowMessage(IntToStr(tv.Items.Item[0].Data^))
и т.д.
← →
Anatoly Podgoretsky © (2005-07-18 16:10) [52]evvcom © (18.07.05 16:04) [49]
Никакой проблемы с DATA надо и работать, а не с копиями.
← →
evvcom © (2005-07-18 16:15) [53]
> Никакой проблемы с DATA надо и работать, а не с копиями.
Я-то знаю, я автора предупреждаю.
← →
mmms (2005-07-18 16:35) [54][50] msguns © (18.07.05 16:05)
msguns, благодарю, так и не получил, горе у меня :(, гроза была в четверг, комп вылетел, не успел почту принять, а аккаунт прописан только там, ладно ноут на гарантии, сдал, сейчас через интерфейс mail.ru зайду, приму.
А что у тебя там лежит - это ты, брат, сам знать должен. Если String, то
Спасибо Ega23, теперь понятно. Только строка ShowMessage(IntToStr(tv.Items.Item[0].Data^)) не компилится, но сейчас разберусь.
← →
Ega23 © (2005-07-18 16:38) [55]ShowMessage(IntToStr(PInteger(tv.Items.Item[0].Data)^))
← →
evvcom © (2005-07-18 16:38) [56]
> не компилится
В таком виде и не скомпилится, потому как Pointer нетипизированный указатель. Могу подсказать как скомпилится, но толку не будет никакого, потому что показывать надо обе стороны: и запись, и чтение. А по отдельности говорить об этом, значит опять AV получить с большой долей вероятности.
← →
msguns © (2005-07-18 16:42) [57]>Ega23 © (18.07.05 16:38) [55]
>ShowMessage(IntToStr(PInteger(tv.Items.Item[0].Data)^))
И ЧТО он увидит ?
← →
evvcom © (2005-07-18 16:43) [58]
> И ЧТО он увидит ?
"100"!
← →
Ega23 © (2005-07-18 16:43) [59]2 msguns © (18.07.05 16:42) [57]
И ЧТО он увидит ?
а ЧТО?????
← →
Anatoly Podgoretsky © (2005-07-18 17:01) [60]Нифига, а увидит он 17
← →
Ega23 © (2005-07-18 17:01) [61]Что положит, то и увидит...
← →
Anatoly Podgoretsky © (2005-07-18 17:03) [62]Ega23 © (18.07.05 17:01) [61]
А я сомневаюсь
← →
Ega23 © (2005-07-18 17:06) [63]2 Anatoly Podgoretsky © (18.07.05 17:03) [62]
А я сомневаюсь
Основание?
← →
msguns © (2005-07-18 17:21) [64]>Ega23 © (18.07.05 17:06) [63]
>Основание?
Для начала ты объясни мне, дураку, что делать вот с этим ?
PInteger(tv.Items.Item[0].Data)^))
Кому и для чего надо значение адреса фиг знает чего ?
← →
Ega23 © (2005-07-18 17:26) [65]2 msguns © (18.07.05 17:21) [64]
var
p:PInteger;
begin
p:=PInteger(tv.Items.Item[0].Data);
ShowMessage(IntToStr(P^));
end;
А такая запись тебя не смущает???
← →
msguns © (2005-07-18 17:36) [66]>Ega23 © (18.07.05 17:26) [65]
Ты мне не ответил на вопрос.
ЧТО лежит В tv.Items.Item[0].Data ?
← →
Ega23 © (2005-07-18 17:39) [67]То, что ты туда поклал. Судя по теме, аффтар кладёт туда указатель на Integer.
В чём проблема-то?
← →
evvcom © (2005-07-19 08:36) [68]
> Судя по теме, аффтар кладёт туда указатель на Integer.
> В чём проблема-то?
Может я чего не углядел, но в [2]Tree.Items.Item[i].Data = Pointer(Query.FieldByName(idParent).asInteger)
я увидел единственное присваивание, и оно совсем не похоже на "кладет указатель". Вот в том-то и проблема, что автор игнорирует советы, что рассматривать чтение/запись надо в паре, но никак не по отдельности.
← →
Ega23 © (2005-07-19 10:36) [69]2 evvcom © (19.07.05 08:36) [68]
Ну я же не виноват, что он этот указатель туда по-идиотски кладёт. Я о том, что он ХОЧЕТ туда положить.
← →
msguns © (2005-07-19 10:43) [70]>Ega23 © (19.07.05 10:36) [69]
>Ну я же не виноват, что он этот указатель туда по-идиотски кладёт. Я о том, что он ХОЧЕТ туда положить.
Вот именно. Чел использует св-во TTreeView.Items[].Data, грубо говоря по-идиотски, не понимая сути. Ты же упорно пытаешься научить его пользоваться именно таким методом, который предусматривает наличие в данных только одного значения какого-либо типа. Так, как ты советуешь, делать можно, конечно.
Но вот нужно ли ?
← →
alex_*** (2005-07-19 10:55) [71]Не проще держать в Data указатель на объект с данными, а список объектов вести в TObjectList?
← →
Ega23 © (2005-07-19 11:25) [72]Вот именно. Чел использует св-во TTreeView.Items[].Data, грубо говоря по-идиотски, не понимая сути. Ты же упорно пытаешься научить его пользоваться именно таким методом, который предусматривает наличие в данных только одного значения какого-либо типа. Так, как ты советуешь, делать можно, конечно.
Но вот нужно ли ?
А ему честно сказал, что всё это по-идиотски. И не только я. Дальше - проблемы автора, ты не находишь?
← →
mmms (2005-07-19 11:46) [73]msguns
Я письма не получил по почте, может архив запароленный, или exe есть? На mail антивирусы это не пропускают, если не сложно перешлите еще раз на этот же адрес, worldsite2000@mail.ru
all
Я эту процедуру взял из FAQ, хотел "прикрутить" под свои нужды. Копирайт тоже есть, во втором посте. Все для меня подходит (формирование меню). Как автор ложит код в итем, я переделывать не стал.
Если можно по другому его туда писать, без переделки самого принципа, то хотелось бы написать. И добавить в FAQ рядом с этим кодом. Т.к. тот код ещё не мало вызовет вопросов у новичков.. Но факт тот, что выбрал имено его, так это простота формирования меню, и минимальный(!) код. Ну а то, что загвоздки с Data.. как ее тогда можно избежать?
← →
msguns © (2005-07-19 11:56) [74]>alex_*** (19.07.05 10:55) [71]
Об этом мы ему и толкуем (см. приведенный выше код)
>mmms (19.07.05 11:46) [73]
Какая версия архиватора ?
Щас пошлю нативные файлы
← →
msguns © (2005-07-19 12:02) [75]лови
← →
mmms (2005-07-19 14:27) [76]Сергей (msguns), я написал вам письмом. Проверте пожалуйста.
← →
msguns © (2005-07-19 15:05) [77]отправил
← →
msguns © (2005-07-19 15:05) [78]Письмо получил, по указанному адресу отправил
← →
mmms (2005-07-19 15:08) [79]Вот теперь дошло, спасибо!
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
Память: 0.71 MB
Время: 0.036 c