Форум: "Основная";
Текущий архив: 2002.10.07;
Скачать: [xml.tar.bz2];
ВнизХранение Integer в Combobox Найти похожие ветки
← →
Влад Утюмов (2002-09-27 07:55) [0]Подскажите новичку, плз наиболее прямой способ решения задачи.
Есть комбобокс на форме. В нем, кроме строк, хочется хранить целочисленные значения (ключи таблицы в БД, но это не важно). Из документации выясняю, что есть
AddItem(Item: String, AObject: TObject)
Вроде то что надо. То что Integer это не TObject - не беда, полминуты - готова обертка вокруг Integer, унаследованная от TObject
И тут натыкаюсь на то, что TStrings не владеет обжектами, что их надо самому удалять. А чтобы самому удалять, надо их еще где-то хранить, и получается уже бред.
Лезут в голову разные мысли, типа поменять поведение TComboBox путем наследования или складывать ссылки на обжекты в отдельную корзину, а потом вытряыхивать разом, или хранить ключи вообще отдельно, в массиве каком-нибудь.
Но думается, что у такой тривиальной и распространенной, ИМХО, задачи не должно быть сложного и уродливого решения. Душа желает простоты.
Влад.
← →
sask (2002-09-27 08:15) [1]IntToStr и StrToInt...
← →
Separator (2002-09-27 08:20) [2]ComboBox1.Items.Add(IntToStr(N)); {N: integer}
N:= StrToInt(ComboBox1.Items.Strings[i]); {но тока если в i-той ячейке храниться число, иначе ошибка}
← →
Song (2002-09-27 08:33) [3]Всю ифнормацию можете хранить в этих же строках. Однако рисовать итемы самому не выводя эту служебную информацию.
← →
MBo (2002-09-27 08:34) [4]ComboBox1.Items.AddObject(AString,Pointer(AInteger));
j:=Integer(ComboBox1.Items.Objects[i]);
Ничего в этом случае выделять не надо, Integer как раз помещается в 4 байтах, уже имеющихся под указатель
← →
kronprince (2002-09-27 09:49) [5]2MBo © (27.09.02 08:34)
Можно и так если быть увереннным что integer не станет снова каким-то Smallint или Int64
Я для этих целей сделал объект TDictionary, если хош скину
← →
MBo (2002-09-27 09:50) [6]>что integer не станет снова каким-то Smallint или Int64
Почему он должен ими стать????
← →
Толик (2002-09-27 10:02) [7]to MBo © (27.09.02 09:50)
Ну ведь был же integer двухбайтовым, сейчас он четырёхбайтовый. И очень вероятно, что грядут времена восьмибайтовых интов...
← →
qube (2002-09-27 10:08) [8]>Ну ведь был же integer двухбайтовым, сейчас он четырёхбайтовый. И >очень вероятно, что грядут времена восьмибайтовых интов...
Тогда, вероятно, и указатели станут 8-байтовыми, а кроме того, вопрос был о комбобоксе, и кажется мне, что добавлять туда числа порядка 2-х миллиардов никто не собирается.
← →
KSergey (2002-09-27 10:22) [9]2 Толик © (27.09.02 10:02)
В принципе вы правы, но как правило программа пишется под определенную версию D, где на таких нюансах вполне можно сыграть (я имею в виду совпадение размеров). При этом если станет small - не страшно, все равно влезет.
← →
Anatoly Podgoretsky (2002-09-27 10:26) [10]MBo © (27.09.02 09:50)
Это generic тип, так что такая возможность очень вероятноь и расчитывать на соместимость по размеру, преобразованию лучше не стоит
← →
Юрий Зотов (2002-09-27 10:27) [11]> Ну ведь был же integer двухбайтовым, сейчас он
> четырёхбайтовый. И очень вероятно, что грядут времена
> восьмибайтовых интов...
И ничего не изменится. Во все времена Integer соответствовал машинному слову. Pointer тоже. Так было и так будет, поскольку это один из основополагающих принципов. Поэтому размеры Integer и Pointer всегда будут совпадать, а только это и требуется.
Но вот плодить объектную оболочку вокруг Integer...
Можно, конечно, и гвозди табуреткой забивать. Но молотком лучше.
← →
KIR (2002-09-27 10:31) [12]Я вообще в этом случае (конкретно когда надо в ComboBox выводить какое либо поле из БД и еще где хранить ключ) делаю так:
Предположим есть некий запрос из которого и надо брать требуемые поля (MyQuery);
Объявляю глобальную переменную IDList: TStringList;
по событию формы OnCreate -> IDList := TStringList.Create;
Затем:
procedure TForm.FillComboBox;
var
IDList: TStringList;
begin
IDList.Clear;
ComboBox1.Clear;
MyQuery.Close;
MyQuery.ExecSQL;
MyQuery.Open;
MyQuery.First;
While not MyQuery.Eof do
begin
ComboBox1.Items.Add(MyQuery["StringField"]);
IDList.Items.Add(IntToStr(MyQuery["ID"]));
MyQuery.Next;
end;
end;
А затем по событию OnClick ComboBox"a:
IDList.ItemIndex := ComboBox1.ItemIndex;
В результате в IDList всегда имею ID нужной записи (ну естественно ID := StrToInt(IDList.Items[IDList.ItemIndex]);
← →
kronprince (2002-09-27 10:32) [13]2Юрий Зотов © (27.09.02 10:27)
>Но вот плодить объектную оболочку вокруг Integer...
Извините, плодить - да, всего лишь с целью запихивания повторяющихся кусков кода и популярных методов работы в один класс
← →
KIR (2002-09-27 10:33) [14]
var
IDList: TStringList
в предыдущем ответе конечно лишнее, sorry :)
← →
Anatoly Podgoretsky (2002-09-27 10:37) [15]Юрий Зотов © (27.09.02 10:27)
Это не совсем так, возьмем для примера 8 битные процессоры, пускай даже от фирмц Интел, адресация была и 12 бит и 16 бит.
Кроме того если посмотрим 16 бит и процессоры 86, 286, 386
Адресная шина 16, 20, 32
Указатель 32 бита seg:ofs
Имподьзовать приведение конечно можно, но следует понимать, что возможно это не будет работать в других версиях
← →
Юрий Зотов (2002-09-27 10:56) [16]> всего лишь с целью запихивания повторяющихся кусков кода и
> популярных методов работы в один класс
Для Integer Ваши "повторяющиеся куски кода и популярные методы работы" сводятся всего лишь к арифметическим операциям.
Хотите написать класс и вызывать его метод Add - пожалуйста, флаг Вам в руки. А я, с Вашего разрешения, уж как-нибудь буду писать по-старинке - просто "+". Думаю, мой вариант будет порождать машинный код примерно на три порядка короче и на пять порядков быстрее. Потому что я предпочитаю писать понятный и эффективный код, а не говорить красивые слова об объектах и технологиях "вообще", безотносительно конкретной задачи.
Поскольку понимаю, что гвозди лучше забивать действительно молотком, а не табуреткой. А вот для сидения молоток как-то не приспособлен, для сидения как раз табуретка лучше.
Не верите? Проверьте.
:о)
← →
Юрий Зотов (2002-09-27 11:11) [17]> Anatoly Podgoretsky © (27.09.02 10:37)
Давайте уточним позиции.
Вы полагаете, что возврат к сегментной адресации возможен? Или к любой ей подобной - то есть, не прямой flat?
Если да - Вы правы. Если нет - прав я.
Потому что, как Вы прекрасно понимаете, никаких Pointer"ов железо вообще не знает - только целые числа, интерпретируемые, как адреса. И понятно, что наибольшая производительность (а к ней, естественно, всегда стремятся) достигается тогда, когда эти числа есть родные машинные слова, и когда используется flat-адресация.
Ведь адресация Seg:Offs появилась не от хорошей жизни, а просто потому, что 64-х Кб, когда-то считавшихся для персоналок достаточными, вдруг оказалось мало. И надо было быстро ликвидировать противоречие, не переделывая в корне разрядность.
А как только пошла 32-битная разрядность, так противоречие автоматически устранилось и снова вернулись к flat. И, думаю, теперь уже навсегда.
← →
Влад Утюмов (2002-09-27 11:17) [18]Неожидал такой бурной дискуссии =)
Внесу немного ясности в спор об размерности Integer.
У меня это ключ таблицы БД. В настоящий момент он имеет размерность 32 бита, но в некоторых ситуациях может оказаться и 64 (распределенные БД например, или очень большие). Поэтому я определил
type oid_t = integer;
(надеюсь не ошибся при переводе с С++ на паскаль), оставив себе пути к отступлению. Этот oid_t я и хочу хранить в комбо, сорри за то то ввел публику в заблуждение.
Получается: кастить его к указателю нежелательно.
Если же число хранить в строке то где хранить сами строки. Или же использовать кодирование типа
15|Строка которую хочу показать
или вообще строки хранить отдельно (уж лучше отдельно хранить цифирьки).
Спасибо всем. Понял.
← →
Юрий Зотов (2002-09-27 11:26) [19]AddObject(строка, TObject(число));
Чтение: Integer(Objects[i]).
Вот и все проблемы. Таким же образом можно вместе со строкой хранить любые данные длиной не более SizeOf(TObject) - то есть, на сегодня 32 бита. Хоть числа, хоть boolean.
← →
kronprince (2002-09-27 11:34) [20]2Юрий Зотов © (27.09.02 10:56)
Извините Юрий - но задача была не про сложение integer а облегчение работы ComboBox с некоторым полем из базы :-\
И в этом случае лучше использовать именно класс
Т.к. может понадобиться не только integer но например Extended или Currency
← →
Anatoly Podgoretsky (2002-09-27 11:56) [21]Юрий Зотов © (27.09.02 11:11)
Давайте, но начнем с того, что суть моего замечания состоит в том, что закладываться на внутрннее представление не стоит, тем более на что то еще не существуещее. Возможно будет достаточно и этого замечания
Давайте уточним позиции.
Вы полагаете, что возврат к сегментной адресации возможен? Или к любой ей подобной - то есть, не прямой flat?
Ходят и такие слухи про новые 64 битные процессоры, но я не думаю, зато гораздо важнее другое, перенос между платформами
Если да - Вы правы. Если нет - прав я.
Потому что, как Вы прекрасно понимаете, никаких Pointer"ов железо вообще не знает - только целые числа, интерпретируемые, как адреса. И понятно, что наибольшая производительность (а к ней, естественно, всегда стремятся) достигается тогда, когда эти числа есть родные машинные слова, и когда используется flat-адресация.
Прекрасно это понимаю, но Integer и Pointer не обязательно должны быть одинаковый длины.
Ведь адресация Seg:Offs появилась не от хорошей жизни, а просто потому, что 64-х Кб, когда-то считавшихся для персоналок достаточными, вдруг оказалось мало. И надо было быстро ликвидировать противоречие, не переделывая в корне разрядность.
Я знаю откуда это и почему, и также знаю почему не спешили делать другое. Д1 наглядный пример.
А как только пошла 32-битная разрядность, так противоречие автоматически устранилось и снова вернулись к flat. И, думаю, теперь уже навсегда.
Я тоже очень на это надеюсь, хотя если взглянуть глубже, от сегментных регистров мы никуда не делись, просто они напрямую не используются и запрещены к использованию, на самом деле мы имеем селектор+смещение в 32 бита (упрощенно конечно), первая половина нас не интересует, если мы не работает на чрезвычайно низком уровне.
Так для информации: 386 процессор в состоянии адресовать до 14 террабайт виртуальной памяти, не знаю используется где либо такая возможность.
Ну и в заключение, то что в начале, для безопасного кода не стоит ставить знак равенства между Integer и Pointer. Думаю с выделенным ты согласен. И второй момент безопасности здесь Integer & TObject тоже не хорошо, хотя практика распространенная.
← →
TTCustomDelphiMaster (2002-09-27 12:02) [22]kronprince © (27.09.02 11:34)
Класс не надо. Можно массив.
← →
kronprince (2002-09-27 12:08) [23]TTCustomDelphiMaster © (27.09.02 12:02)
TDictionary = class
protected
sFieldID :string;
sFieldName:string;
private
aiRec : TAInteger; // ID_REC
asName: TAString; //
← →
MBo (2002-09-27 12:35) [24]Хорошо, пусть потребуется хранить не 4-байтовое, а другое (больше размера указателя).
Опять же класс ни к чему
type PInt64=^Int64;
var p:PIint64;
new(p);
p^:=12345678901234;
Items.AddObject("ww",TObject(p));
...
Int64Var:=Pint64(Items.Objects[i])^;
точно так же и с записями - определяем тип указателя на нее и вперед.
Класс же нужен в тех случаях, когда соотв. объект (в широком смысле) должен быть активен или обеспечивать нетривиальный доступ к своим полям.
← →
TTCustomDelphiMaster (2002-09-27 12:38) [25]kronprince © (27.09.02 12:08)
> Подскажите новичку, плз наиболее прямой способ решения задачи...
> ... не должно быть сложного решения. Душа желает простоты.
← →
kronprince (2002-09-27 12:59) [26]TTCustomDelphiMaster © (27.09.02 12:38)
Это как Вы заметили писалось для специфичных нужд
Вырезать легче :)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.10.07;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.008 c