Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.11.25;
Скачать: CL | DM;

Вниз

Добавление объектов в ComboBox (Tobject(string))   Найти похожие ветки 

 
Nike85   (2007-11-02 15:25) [0]

Здравствуйте!
Не могу понять, чем вызвана следующая проблема:
читаю из бд данные - имя записи (name) и строковое представление идентификатора (anrec), добавляю их в расположенный на форме комбобокс (имя - как строку, идентификатор - в список объектов). Однако при дальнейшем выводе идентификатора - выходит абракадабра (пустое сообщение - такое ощущение, что где-то утечка памяти).
Код ниже:

//Чтение данных:
//s1,s2: string;
 while not tempQuery1.Eof do
   begin
   s1:=tempQuery1.FieldByName("name").AsString;
   s2:=tempQuery1.FieldByName("anrec").AsString;
   ShowMessage(s2);
   cmbStatus.Items.AddObject(s1,Tobject(s2));
   TempQuery1.Next;
   end;



//Вывод данных:
ShowMessage(string(cmbStatus.Items.Objects[cmbStatus.ItemIndex]));


 
Nike85   (2007-11-02 15:27) [1]

в чем проблема? почему теряются данные? Как это можно исправить? Подскажите, пожалуйста, горю.


 
Kolan ©   (2007-11-02 15:29) [2]

А не заюзать ли тебе TDBLookUpComboBox?


 
Reindeer Moss Eater ©   (2007-11-02 15:34) [3]

После заполнения списка с объектами, как только выходим за пределы процедуры и все неявные строки (TField.AsString) выходят за пределы видимости и умирают, все объекты в списке начинают указывать на мусор.


 
Nike85   (2007-11-02 15:36) [4]

Как сделать "вечно живущие" объекты? не заводить же для это глобальные переменные? Я пока делаю так - для каждого комбобокса - их уже штуки 4 у меня на форме,я сделал объекты Tstringlist. Но это мне кажется как-то коряво


 
Reindeer Moss Eater ©   (2007-11-02 15:37) [5]

Переменные не нужны. Нужно явно распределять память под строки


 
Юрий Зотов ©   (2007-11-02 15:39) [6]

> Nike85   (02.11.07 15:25)

Разве строка - это объект?

Строка имеет управляемое время жизни и как только счетчик ссылок на нее обнуляется, занимаемая ею память автоматически освобождается (и, соответственно, ссылки на нее становятся недействительными). У Вас это происходит со строкой s2 на каждом новом витке цикла.

Используйте Names и Values.


 
Nike85   (2007-11-02 15:40) [7]

To Reindeer Moss Eater ©  :
Это как, можно по-подробнее? Pchar-ом пользоваться? можно код? Объясните дураку

To Kolan © :
Дблукап не хотелось бы использовать. Да и тут уже дело принципа - как заставить комбобокс хранить свои объекты :))


 
Reindeer Moss Eater ©   (2007-11-02 15:41) [8]

cmbStatus.Items.AddObject(s1,TObject(StrNew(PChar(s2))));


 
Nike85   (2007-11-02 15:50) [9]

To Юрий Зотов © :
строка - не объект, это не си шарп. Или нет??

To Reindeer Moss Eater ©
Ок, че я где-то подобное уже видел. Создать объект новый надо было. Спасибо, кажется так заработает. Сейчас проверю. А освобождать объекты надо как, например при очистке списка перед его новым заполнением?
for i:=cmbStatus.Items.Count-1 downto 1 do
cmbStatus.Items.Objects[i].Free;


Правильно я понимаю или нет?


 
Nike85   (2007-11-02 15:51) [10]

только не даунту 1, а 0 :))


 
Reindeer Moss Eater ©   (2007-11-02 15:52) [11]

Ну подумай, если память распределялась с помощью StrNew, то чем же надо её освобождать?


 
Nike85   (2007-11-02 15:56) [12]

Возможно вот так?

for i:=cmbStatus.Items.Count-1 downto 0 do
StrDispose(Pchar(cmbStatus.Items.Objects[i]));
cmbStatus.Clear;

А что будет если вызывать Objects[i].Free?


 
Reindeer Moss Eater ©   (2007-11-02 15:58) [13]

А попробуй.

Зачем Free, если никто Create не делал?


 
Kolan ©   (2007-11-02 16:00) [14]

Вставлю своё имхо. Данные не надо хронить в ComboBox"е или пользуй DB Aware контрол
или (как сделал бы я) метериализуй объекты из БД и хрони их в отдельном списке. При надобности синхронизируй список с комбо и наоборот&#133


 
Nike85   (2007-11-02 16:04) [15]

сможет ли Object удалить себя, вызывая Free, даже если обжект представлен Pchar-ом? Конечно, если использовать приведение к пчару, то можно удалять и через strdispose. Только вот вопрос теперь у меня такой, если вызвать Objects[i].Free, хватит ли сил объекту Тобжект корректно удалить себя, даже если внутри него инкапсулирован Пчар, или допустим объект Tform. В каком случае будет выше производительность? - если через strDispose,  или через метод  Tobject?


 
Nike85   (2007-11-02 16:08) [16]

To Kolan © :
А зачем я буду синхронизировать комбо с внешним списком, если при хранении в комбобоксе данные всегда будут синхронизованы (даже если я буду пересортировывать строки комбо, то автоматом и будут пересортировываться объекты, с ними связанные (а может и не будут :))). Да и внешний список - это еще одна явно объявленная переменная, модуль читать не удобно. Не, мне больше вариант с хранением в комбо нравится


 
Anatoly Podgoretsky ©   (2007-11-02 16:09) [17]

> Nike85  (02.11.2007 15:36:04)  [4]

Глобальную конечно завести можно, она удаляться не будет, но и все объекты будут одинаковы.


 
Anatoly Podgoretsky ©   (2007-11-02 16:10) [18]

> Reindeer Moss Eater  (02.11.2007 15:52:11)  [11]

Как чем, с помощью справки конечно, бить ею по голове до полного просветления.


 
Anatoly Podgoretsky ©   (2007-11-02 16:10) [19]

> Nike85  (02.11.2007 15:56:12)  [12]

> А что будет если вызывать Objects[i].Free?

Ой не делай этого, будет больно.


 
clickmaker ©   (2007-11-02 16:19) [20]


> [15] Nike85   (02.11.07 16:04)
> сможет ли Object удалить себя, вызывая Free, даже если обжект
> представлен Pchar-ом?

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


 
Kolan ©   (2007-11-02 17:18) [21]

> если при хранении в комбобоксе

Дело в том что комбо — это элемент интерфейса и он не очень то пригоден для хронения данных.
В любом случае даже при использовании комбо, лучьше матеарелизовывать объект(с понятным именем и внятными полями) и сохронять его&#133


 
Kolan ©   (2007-11-02 17:22) [22]

TMyObject = class
private
 FName: string;
 FAnrec: string;  //ХЗ что есть anrec&#133
public
 constructor Create(Name, Anrec: string);
end;


//Чтение данных:
//s1,s2: string;
while not tempQuery1.Eof do
begin
  with tempQuery1 do
    cmbStatus.Items.AddObject(s1, TMyObject.Create(FieldByName("name").AsString,
      FieldByName("anrec").AsString));  
  TempQuery1.Next;
end;


Написание савойств, кода конструктора — дом. задание.


 
Юрий Зотов ©   (2007-11-03 23:50) [23]

> Nike85   (02.11.07 15:50) [9]

В Delphi строка - это не объект. Это Pointer на Record специального (compiler-magic) типа. Структура такая:

-8: Счетчик ссылок
-4: Длина тела в байтах
0: Тело строки, заканчивающееся нулем (ASCIIZ)

Хранятся строки в динамической памяти, а рулит всей этой фигней компилятор. В частности, он же вставляет код изменения счетчика ссылок и код освобождения памяти, если счетчик ссылок стал нулевым.

Но компилятор - не человек, и даже не ИИ. Поэтому он не понимает, что при выполнении кода
TStrings.AddObject(s1, TObject(s2)
счетчик ссылок в строке s2 должен быть увеличен. Он его и не увеличивает. Поэтому, как только переменная s2 получает новое значение, ее старое значение уничтожается и Objects[i] начинает ссылаться в никуда.



Страницы: 1 вся ветка

Текущий архив: 2007.11.25;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.016 c
15-1192716641
Delphi User
2007-10-18 18:10
2007.11.25
Каким фаерволом вы пользуетесь ? Outpost слишком тяжелый.


15-1193245265
harisma
2007-10-24 21:01
2007.11.25
Нужен компонент


15-1191929132
Nucer
2007-10-09 15:25
2007.11.25
Ever more


2-1194249160
ASDE
2007-11-05 10:52
2007.11.25
RegisterServiceCtrlHandlerEx


2-1194208293
Xak
2007-11-04 23:31
2007.11.25
Как правельно запустить *.bat