Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.01.2008, 15:15   #11
Mitron
Форумчанин
 
Аватар для Mitron
 
Регистрация: 10.05.2007
Сообщений: 117
По умолчанию

может дадите ссылочку на русский вариант, а то с английским как то не сильно дружу ....

Скиньте пожалуйста ссылку на рускоязычный туториал,а то везде английский да немецкий ((
Задачи на заказ

Блажен тот, кто ничего не знает: он не рискует быть не понятым.

Последний раз редактировалось Stilet; 19.07.2010 в 08:33.
Mitron вне форума Ответить с цитированием
Старый 30.01.2008, 19:29   #12
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

В королевстве вроде была статья...
BOBAH13 вне форума Ответить с цитированием
Старый 30.01.2008, 20:11   #13
Mitron
Форумчанин
 
Аватар для Mitron
 
Регистрация: 10.05.2007
Сообщений: 117
По умолчанию

подскажите еще какойнибудь источник, что-то запасы королевства иссякают((
Задачи на заказ

Блажен тот, кто ничего не знает: он не рискует быть не понятым.
Mitron вне форума Ответить с цитированием
Старый 06.07.2010, 17:09   #14
AnTe
Форумчанин
 
Регистрация: 25.09.2008
Сообщений: 209
По умолчанию

подниму старую темку.

Пожалуй, единственный обширный хелп, на русском языке, я нашёл какую-то pdf-ку. К сожалению, потерял ссылку, а та, что указана в документе: Последняя версия статьи и исходные коды всех проектов, представленных в материалах статьи, всегда могут быть скачаны по адресу:
http://quadr0.pochta.ru/VirtualTreev...altreeview.zip
Версия статьи в Adobe PDF формате доступна по адресу:
http://quadr0.pochta.ru/VirtualTreev...eeview_pdf.zip
- не работает)

по всей видимости, исходник, т.е. как это всё создавалось, тут: http://forum.vingrad.ru/forum/topic-...ml#st_0_view_0

В принципе, это всё. С оф.сайта, почему-то не получается выкачать родную документацию, на английском, но всё равно, ищу максимум информации на русском, может, кто-нибудь подскажет?

и у меня следующий вопрос, нельзя ли к узлам привязать ОБЪЕКТЫ ?

В примерах связывают только record, причём каким-то мудрёным образом:

Код:
type
PPhoneNode = ^TPhoneNode;
TPhoneNode = record
Name, // Имя контакта
Phone: WideString; // Телефон
end;
...

VT.NodeDataSize := SizeOf(TPhoneNode);
....

procedure TfrmMain.BtnAddClick(Sender: TObject);
var
NewNode: PVirtualNode;
NewPhone: PPhoneNode;
begin
NewNode := VT.AddChild(VT.FocusedNode);
NewPhone := VT.GetNodeData(NewNode);
if Assigned(NewPhone) then
with NewPhone^ do
begin
Name := EdName.Text;
Phone := EdPhone.Text;
end;
end;
Меня смущает конструкция:
Код:
NewPhone := VT.GetNodeData(NewNode);
with NewPhone^ do
...
в NewPhone, при выполнении первой строки - мусор! По всей логике, должно быть наоборот, в NewNode, в свойство Data, присваивать ссылку на NewPhone, например, сразу в методе Add, полное объявление которого

Цитата:
function TBaseVirtualTree.AddChild(Parent: PVirtualNode; UserData: Pointer = nil): PVirtualNode;
Несмотря на то, что тип хранимых данных - pointer, я попробовал создавать узлы примерно так: AddChild(VN, MyObject1) (TMyObject = class ..., VT.NodeDataSize := SizeOf(TMyObject))

а затем, в GetText приводить обратно:

MyObj := TMyObject(AddChild.GetNodeData(...) ) - вываливается с каким-то исключением (завтра проверю)

у меня есть куча объектов, с полиморфными функциями, которые хотелось бы привязать, к дереву, record-ами уже и пользоваться разучился , всё на классах построено, такой вроде замечательный компонент, и такой странный затык
AnTe вне форума Ответить с цитированием
Старый 12.07.2010, 11:23   #15
AnTe
Форумчанин
 
Регистрация: 25.09.2008
Сообщений: 209
По умолчанию

Уфф, припарился окончательно.

Код:
 PRec = ^TRec;
  TRec = record
    name: string;
    num: integer;
    obj: TObject;
  end;
...

Код:
procedure TfmTest.btnGoClick(Sender: TObject);
var
  NewNode: PVirtualNode;
  Rec: PRec;
begin
  VT.NodeDataSize := SizeOf(TRec);
  NewNode := VT.AddChild(VT.FocusedNode);
  Rec := VT.GetNodeData(NewNode);
  if Assigned(Rec) then
    with Rec^ do
    begin
      Name := 'Test';
      num := 0;
      Obj := TObject.Create;
      showmess(obj.ClassName); // Выводит "TObject"
    end;
end;

Код:
procedure TfmTest.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
 Data: PRec;
begin
 Data := Sender.GetNodeData(Node);
 if Assigned(Data) then
 begin
  CellText := Data^.Name; // работает
  CellText := Data^.Obj.ClassName; // не работает! в Obj лежит nil!
  end;
end;
сформулирую вопрос:

как в VirtualTreeView привязать к узлам дерева объекты?

в узлах TreeView от делфей, есть прекрасное свойство Data, которое имеет тип pointer. Через это свойство я и привязывал к узлу свой объект.

В VirtualTreeView механизм какой-то муторный. Внутри хранятся данные типа "запись", доступ - через мудрёный метод GetNodeData(Node).

Я думаю, проблема где-то в нём:

Код:
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;
Что можно сделать?

Последний раз редактировалось AnTe; 12.07.2010 в 13:01.
AnTe вне форума Ответить с цитированием
Старый 14.07.2010, 11:18   #16
AnTe
Форумчанин
 
Регистрация: 25.09.2008
Сообщений: 209
По умолчанию Немного разобрался.

Имеем

TreeView - свойство Data: Pointer
VirtualTreeView - метод GetNodeData: Pointer;

пишу две процедуры
Код:
procedure TfmTest.btnTreeViewClick(Sender: TObject);
var TN: TTreeNode;
begin
  TN := TreeView1.Items.AddFirst(nil, 'First');
  TN.Data := TObject.Create; // положил
  ShowMessage(Tobject(TN.Data).ClassName);  // вывел, успешно
end;


procedure TfmTest.btnVirtualTreeViewClick(Sender: TObject);
var
  NewNode: PVirtualNode;
begin
  VT.NodeDataSize := SizeOf(TObject);
  NewNode := VT.AddChild(nil, TObject.Create); // положил
  ShowMessage(Tobject(VT.GetNodeData(NewNode)).ClassName); // вывел, неуспешно, т.к. по какой-то причине нужно использовать p^
end;
ShowMessage(Tobject(VT.GetNodeData( NewNode)^).ClassName);
Работает превосходно

После разбирательств выяснена причина, в методе GetNodeData:
Result := PByte(@Node.Data) + ....
т.е. реально результат возращает указатель, на указатель!
потому то крышечку и надо ставить

я всё никак не пойму, с какой целью эти танцы с бубном производятся?
неужто, чтобы данные типа record хранить в дереве?
ЗАЧЕМ??
AnTe вне форума Ответить с цитированием
Старый 14.07.2010, 11:33   #17
Korben5E
Форумчанин
 
Аватар для Korben5E
 
Регистрация: 13.07.2010
Сообщений: 346
По умолчанию

Цитата:
Сообщение от AnTe Посмотреть сообщение
Имеем

TreeView - свойство Data: Pointer
VirtualTreeView - метод GetNodeData: Pointer;

пишу две процедуры
Код:
это собитие при щелчке на существующий елемент
заполнение происходит или при создании формы или в процессе работы

procedure TfmTest.btnTreeViewClick(Sender: TObject);
var TN: TTreeNode;
begin
  TN := TreeView1.Items.AddFirst(nil, 'First');


  TN.Data := TObject.Create; // положил
и ложить сюда ты будешь при каждом щелчке......

  ShowMessage(Tobject(TN.Data).ClassName);  // вывел, успешно
end;


procedure TfmTest.btnVirtualTreeViewClick(Sender: TObject);
var
  NewNode: PVirtualNode;
begin
  VT.NodeDataSize := SizeOf(TObject);


  NewNode := VT.AddChild(nil, TObject.Create); // положил
  ShowMessage(Tobject(VT.GetNodeData(NewNode)).ClassName); 


// вывел, неуспешно, т.к. по какой-то причине нужно использовать p^
end;
ShowMessage(Tobject(VT.GetNodeData( NewNode)^).ClassName);
Работает превосходно

После разбирательств выяснена причина, в методе GetNodeData:
Result := PByte(@Node.Data) + ....
т.е. реально результат возращает указатель, на указатель!
потому то крышечку и надо ставить

я всё никак не пойму, с какой целью эти танцы с бубном производятся?
неужто, чтобы данные типа record хранить в дереве?
ЗАЧЕМ??

элемент Node.Data - это указатель, размер которого равен машинному слову - для тебя 4 байта и не более (это болезнь всех кто не учит язык С(си))

по этому ты можешь вписать в Data только указатель на объект в памяти

если ты объявляешь переменную типа ОБЪЕКТ(не обязательно TObject)- то она уничтожается при выходе из процедуры

ты должен создать переменную типа указатель ОБЪЕКТ(^....)
в этот указатель выделить память для объекта

и добавить этот объект с помощью AddObject или AddChildObject

при получении данных да с помощью кастинга присваиваешь Node.Data
в перменную

xx: PRec;
begin
xx := PRec(Node.Data);

потом работаешь с хх как с обычной структурой

уточни что ты вообще хочешь от дерева с объектами
Non est culpa vin, sed culpa bibentis

Последний раз редактировалось Korben5E; 14.07.2010 в 11:39.
Korben5E вне форума Ответить с цитированием
Старый 14.07.2010, 14:12   #18
AnTe
Форумчанин
 
Регистрация: 25.09.2008
Сообщений: 209
По умолчанию

Спасибо за ответ!
Цитата:
Сообщение от Korben5E Посмотреть сообщение
это собитие при щелчке на существующий елемент
заполнение происходит или при создании формы или в процессе работы
...
и ложить сюда ты будешь при каждом щелчке......
Это тестовая форма, кнопка нажимается только один раз, как раз для теста



Цитата:
элемент Node.Data - это указатель, размер которого равен машинному слову - для тебя 4 байта и не более (это болезнь всех кто не учит язык С(си))
Именно так, посему в "VT.NodeDataSize := SizeOf(TObject);", SizeOf используется для лаконичности, наглядности и на будущее. Тем более, один хрен вычислится всего один раз, да, наверное, на этапе компиляции

Цитата:
по этому ты можешь вписать в Data только указатель на объект в памяти
Вот я и указываю, на TObject.Create, переменные объектов в делфях по умолчанию указатели.

Цитата:
если ты объявляешь переменную типа ОБЪЕКТ(не обязательно TObject)- то она уничтожается при выходе из процедуры
Наоборот! Объекты не удаляются, пока сам не грохнешь, и приводят к утечкам, если так и забудешь грохать! Ведь сборщик мусора в делфях, по кр.мере в 7х, отсутствует!

Для переменных типа "запись" - это верно, уничтожится, при выходе из процедуры.

Цитата:
ты должен создать переменную типа указатель ОБЪЕКТ(^....)
в этот указатель выделить память для объекта
Всё таки это лишнее, что видно из кода процедуры для стандартного TreeView. Никуда обжекты не деваются, все живут.


Цитата:
при получении данных да с помощью кастинга присваиваешь Node.Data
в перменную

xx: PRec;
begin
xx := PRec(Node.Data);

потом работаешь с хх как с обычной структурой
Да вот только PRec у меня как раз не сработал

Код:
PRec = ^TRec;
  TRec = record
    name: string;
    num: integer;
    obj: TObject;
  end;

procedure TfmTest.btnGoClick(Sender: TObject);
var
  NewNode: PVirtualNode;
  Rec: PRec;
begin
  VT.NodeDataSize := SizeOf(TRec);
  NewNode := VT.AddChild(VT.FocusedNode);
  Rec := VT.GetNodeData(NewNode);
  if Assigned(Rec) then
    with Rec^ do
    begin
      Name := 'Test';
      num := 0;
      Obj := TObject.Create;
      showmess(obj.ClassName); // Выводит "TObject"
    end;
end;

procedure TfmTest.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
 Data: PRec;
begin
 Data := Sender.GetNodeData(Node);
 if Assigned(Data) then
 begin
  CellText := Data^.Name; // работает
  CellText := Data^.Obj.ClassName; // не работает! в Obj лежит nil!
  end;
end;
почему объект из записи самоудалился - загадка

Цитата:
уточни что ты вообще хочешь от дерева с объектами
Уу

Как я уже писал, по стилю программирования, уже и позабыл как страшное слова слово "запись", всё делаю обычно на объектах. Так и здесь.

Во-первых (в главных) у меня уже есть куча объектов, в моей программе, данные из которых я хочу отобразить, в виде дерева.

Во-вторых, объекты от одного прародителя (пусть он зовётся "TMyObject"), у которого я делаю виртуальный метод, что-нибудь вроде "function TMyObject.GetTextForVT: string", ну и ещё кучку методов, выдача иконок, и что там ещё есть.

В обработчиках событий дерева напишу что-то вроде

Код:
procedure TfmTest.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText:WideString);
begin
  CellText := TMyObject(VT.GetNodeData(NewNode)).ClassName;
end;
Всё, можно забыть про преобразование данных, и для каждого типа выводить по своему текст, иконку, и т.д., например, для текста, всего лишь указав этот текст в перекрытом методе "GetTextForVT".

В ином случае, если я правильно понимаю, мне нужно будет всё это реализовывать
в обработчике "procedure TfmTest.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);", организовывая сложные ветвления, вычисляя каждый раз по-разному текст.
AnTe вне форума Ответить с цитированием
Старый 14.07.2010, 14:53   #19
Korben5E
Форумчанин
 
Аватар для Korben5E
 
Регистрация: 13.07.2010
Сообщений: 346
По умолчанию

Цитата:
Сообщение от AnTe Посмотреть сообщение
Спасибо за ответ!
Это тестовая форма, кнопка нажимается только один раз, как раз для теста

Именно так, посему в "VT.NodeDataSize := SizeOf(TObject);", SizeOf используется для лаконичности, наглядности и на будущее. Тем более, один хрен вычислится всего один раз, да, наверное, на этапе компиляции

Вот я и указываю, на TObject.Create, переменные объектов в делфях по умолчанию указатели.

Наоборот! Объекты не удаляются, пока сам не грохнешь, и приводят к утечкам, если так и забудешь грохать! Ведь сборщик мусора в делфях, по кр.мере в 7х, отсутствует!

Для переменных типа "запись" - это верно, уничтожится, при выходе из процедуры.

Всё таки это лишнее, что видно из кода процедуры для стандартного TreeView. Никуда обжекты не деваются, все живут.

Да вот только PRec у меня как раз не сработал
вот в том-то все и дело - дельфа скрывает данный механизм от программера и когда появляется необходимость - программер заходит в тупик

Вот пример на С++, сразу скажу что VCL это не поддерживают

тут мы создаем указатель на объект, который планируем создать далее (типа вызвать Create)
TMyObject *obj1;

а тут мы сразу создаем объект... со всеми свойствами, функциями и т.п.
т.е. конструктор отработает именно в этой точке
TMyObject obj2;

если бы такой строгий паскаль, не был таким лояльным с такими операциями - то и вопросов-бы не возникало

вот тебе наваял - на форме 3 компонента, триивьюв и 2 лейбела

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls;

type
PRec = ^TRec;
  TRec = record
    name: string;
    num: integer;
    obj: TObject;
  end;

  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Label1: TLabel;
    Label2: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
node : TTreeNode;
r : PRec;
begin
    r := New(PRec);
    r.name := 'ROOOT';
    r.num := 11;
    //r.obj :=

    node := TreeView1.Items.AddObject(nil,'root',r);
    r := New(PRec);
    r.name := 'ITEM111';
    r.num := 1222;

    TreeView1.Items.AddChildObject(node,'Item1',r);
    r := New(PRec);
    r.name := 'ITEM222';
    r.num := 1333;
    TreeView1.Items.AddChildObject(node,'Item2',r);

    r := New(PRec);
    r.name := 'ITEM333';
    r.num := 1444;
    TreeView1.Items.AddChildObject(node,'Item3',r);

end;

procedure TForm1.FormDestroy(Sender: TObject);
var
   r : PRec;
   i : integer;
begin
    While TreeView1.Items.Count > 0 do
    begin
        i := TreeView1.Items.Count-1;
        r := TreeView1.Items.Item[i].Data;
        Dispose(r);
        TreeView1.Items.Item[i].Delete
    end;
end;

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
    r : PRec;
begin
    r := Node.Data;
    Label1.Caption := 'Text in Data pointer '+ r.name + ' with labeled text - ' + Node.Text;
    Label2.Caption := 'Number in Data pointer:'+IntToStr(r.num);
end;

end.
Non est culpa vin, sed culpa bibentis
Korben5E вне форума Ответить с цитированием
Старый 15.07.2010, 04:53   #20
AnTe
Форумчанин
 
Регистрация: 25.09.2008
Сообщений: 209
По умолчанию

Цитата:
Сообщение от Korben5E Посмотреть сообщение
вот в том-то все и дело - дельфа скрывает данный механизм от программера и когда появляется необходимость - программер заходит в тупик
ммм... про какой механизм идёт речь?
Вопросы возникли по стороннему компоненту,
Virtual Treeview http://www.soft-gems.net

Цитата:
Вот пример на С++, сразу скажу что VCL это не поддерживают

тут мы создаем указатель на объект, который планируем создать далее (типа вызвать Create)
TMyObject *obj1;

а тут мы сразу создаем объект... со всеми свойствами, функциями и т.п.
т.е. конструктор отработает именно в этой точке
TMyObject obj2;

если бы такой строгий паскаль, не был таким лояльным с такими операциями - то и вопросов-бы не возникало
В паскале нужно вызвать obj2 := TMyObject.create явно, т.о. переменная ВСЕГДА будет ссылкой, если я правильно понимаю, но мне это никогда не мешало...

Цитата:
вот тебе наваял - на форме 3 компонента, триивьюв и 2 лейбела
Спасибо, но что он демонстрирует? Да, память под переменную типа "запись", можно выделить отдельно, при помощи оператора new, и действительно это не слишком затратно, в реализации.

У меня была проблема с передачей в VT объекта, а после решения проблемы, я задумался над тем, ЗАЧЕМ в VT с полем DATA придуманы такие сложности.
AnTe вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вопрос по компаненту VirtualTreeView gyvenor Компоненты Delphi 13 28.02.2007 11:34