Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> VitrualDrawTree указатели, Одна запись для двух элементов списка 
V
    Опции темы
halfhope
Дата 12.8.2012, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 31.5.2010

Репутация: нет
Всего: нет



Не подскажете решение моей проблемы?!
Есть контакт лист с пользователями, где есть два типа записей(record) "User" и "Group". Каждый User может входить в несколько групп. 
При создании записи пользователя vdt получает указатель на запись пользователя, при создании дубликата пользователя(в случае если пользователь содержится в нескольких списках) я не знаю как "сказать vdt" чтобы он его дублировал, а не создавал новую запись(т.е. пользователя). 
Это сказывается при смене параметров записи. Например, Пользователь вошел в сеть, ему нужно поставить статус Online. Я ставлю, но статус присваивается только одному пользователю т.е. его дубликаты имеют каждый свою запись, а нужно чтобы все ссылались на одну запись. Прошу помочь тех, кто работал с vdt.
Код

{Процесс добавления пользователя в vdt}
                for x := 0 to gidslist.Count-1 do //Цикл считывания групп пользователя
                  begin
                    if x = 0 then//Проверяется количество групп
                    begin
                      {Этот код выполняется при добавлении пользователя в группу}
                      newNodeUser := vdt1.AddChild(GetGroupByID(StrToInt(gidslist[x])));//Добавление нового элемента в vdt
                      nodeUser := vdt1.GetNodeData(newNodeUser);//Присвоение элементу указателя на данные пользователя
                      {Загрузка данных пользователя}
                      nodeUser^.id := rootUsers.Nodes[i].ReadAttributeInteger('id',0);
                      nodeUser^.fname := rootUsers.Nodes[i].ReadAttributeUnicodeString('fname','');
                      nodeUser^.lname := rootUsers.Nodes[i].ReadAttributeUnicodeString('lname','');
                      nodeUser^.activity := rootUsers.Nodes[i].ReadAttributeUnicodeString('activity','');
                      nodeUser^.sex := rootUsers.Nodes[i].ReadAttributeBool('sex',false);
                      nodeUser^.online := Boolean(Random(2));
                      nodeUser^.av := TPNGObject.Create;
                      nodeUser^.av.LoadFromFile(dest + 'avatars/' + IntToStr(nodeUser^.id) + '.png');
                      {Эти две строки я создал, чтобы создать хотя бы дубликат с одинаковыми данными}
                      lastNode := newNodeUser;
                      lastNodeUser := nodeUser;
                    end
                    else
                      begin
                       {А этот код выполняется при добавлении дубликата пользователя в группу
                       Вот здесь я не могу создать дубликат с указателем на данные оригинала}
                        //newNodeUser :=  vdt1.AddChild(GetGroupByID(StrToInt(gidslist[x])));
                        newNodeUser :=  vdt1.AddChild(GetGroupByID(StrToInt(gidslist[x])));
                        lastNodeUser := vdt1.GetNodeData(newNodeUser);
                        lastNodeUser^ := nodeUser^;
                        //У меня все равно получается два разных человека в разных группах, вместо одного.
                      end;
                  end;
              end

Вот скрин.
user posted image


PM MAIL   Вверх
kami
Дата 12.8.2012, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Как-то так:

Код

ExistingNodeData:=vt.GetNodeData(ExistingUserNode);
vt.InsertNode(GroupNode, amAddChildLast, ExistingNodeData^);

Единственное - нужно проверить, будет ли нормально обрабатываться ситуация, когда один нод удален и пошло обращение ко второму, содержащему ссылку на тот же элемент.
PM MAIL WWW   Вверх
halfhope
Дата 15.8.2012, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 31.5.2010

Репутация: нет
Всего: нет



Все равно не получается, выложу сорцы. Может я что-то не так делаю?!. Просто первый раз с указателями работаю, но вроде бы тут все просто. 
Да, спасибо, совсем забыл про обработку такой ситуации. 
Там в onCreate формы идет добавление. А cList.pas это обертка отрисовки для vdt.

Это сообщение отредактировал(а) halfhope - 15.8.2012, 12:53

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  cList_2012_08_15_15_46_46.rar 616,40 Kb
PM MAIL   Вверх
kami
Дата 15.8.2012, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(halfhope @  15.8.2012,  12:51 Найти цитируемый пост)
выложу сорцы.

Слишком много смотреть. Куча лишнего, не относящегося к задаче.

Показываю свой пример, в котором всё дублируется так, как нужно. Правда, на VirtualStringTree, но сути дела не меняет - все задействованные методы VT относятся к BaseVirtualTree.

Код

type
  TUser = record
    UserName: string;
  end;
  PUser = ^TUser;
=================================
procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  Node: PVirtualNode;
  us: PUser;
begin
  // наполняем VT десятью юзерами
  for i := 0 to 9 do
    begin
      New(us);
      us.UserName := 'User' + IntToStr(i);
      vt1.InsertNode(nil, amAddChildLast, us);
    end;
end;

procedure TForm1.vt1GetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
begin
  NodeDataSize := SizeOf(PUser);
end;

procedure TForm1.vt1GetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: string);
var
  us: PUser;
begin
  us := PUser(Sender.GetNodeData(Node)^);
  CellText := us.UserName;
end;

// по даблклику на любом ноде создаем ему дитё, и в NodeData дитя заносим ссылку на того же юзверя.
procedure TForm1.vt1DblClick(Sender: TObject);
var
  us: PUser;
begin
  if vt1.GetFirstSelected = nil then
    Exit;
  us := PUser(vt1.GetNodeData(vt1.GetFirstSelected)^);
  vt1.InsertNode(vt1.GetFirstSelected, amAddChildLast, us);

  // замечание: если бы record-ы пользователей дублировались, то
  // значение UserName менялось бы только у одного - находящегося в фокусе.
  // а так как NodeData указывает на одного и того же user-а, то
  // и значение UserName меняется у всех (вернее, у одного и того же,
  // просто он отображается несколько раз'
  us.UserName := 'ChangedUser. ChildNodeCount = ' + IntToStr(vt1.GetFirstSelected.ChildCount);
  vt1.Invalidate;
  // если так поклацать по VT, насоздавать "детей", и "детей детей", и "детей детей детей", а потом опять "детей детей" и так далее, то становится всё очевиднее,
  // что юзер-то один, а отображений его много
end;


Это сообщение отредактировал(а) kami - 15.8.2012, 13:57
PM MAIL WWW   Вверх
halfhope
Дата 15.8.2012, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 31.5.2010

Репутация: нет
Всего: нет



Огромное спасибо, за помощь. Разобрался, все работает. 
PM MAIL   Вверх
kami
Дата 15.8.2012, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(halfhope @  15.8.2012,  15:32 Найти цитируемый пост)
Разобрался, все работает. 

Еще раз хочу заострить внимание:
Цитата(kami @  12.8.2012,  16:26 Найти цитируемый пост)
нужно проверить, будет ли нормально обрабатываться ситуация, когда один нод удален и пошло обращение ко второму, содержащему ссылку на тот же элемент.

Иначе пойдут или AV (что предпочтительнее), или будет использоваться и отображаться мусор вместо реальных данных.
PM MAIL WWW   Вверх
halfhope
Дата 15.8.2012, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 31.5.2010

Репутация: нет
Всего: нет



Ну, этим займется рекурсивный поиск. В обертке допишу override ф-ию, которая при удалении нода будет искать и удалять ноды, указывающие на ту же запись. Пожалуй сейчас этим и займусь. Осталось дело за малым, нужно, чтобы текст не вмещающийся в отрисованный нод сжимался "обрезался". Пожалуй, заранее размеры для текста лучше задавать при onResize, а не при onDrawNode так будет "экономичней" и правильнее. А при отрисовке он просто будет брать данные ширины из уже "готовой к новым размерам" переменной. Спасибо за совет. Очень приятно, что такие люди есть)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0900 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.