Перейти к содержанию
Fire Monkey от А до Я
  • 0

Связь ListBox и SQLite. (Подобие справочника)


maxfad

Вопрос

Существует база данных SQLite из двух таблиц: категории(kategorii) и разделы(razdel). В категориях три поля: ID.NAM1,kateg(Nam1 уникальные значения), разделы :  ID.NAM2,KATEG2(категории одинаковы для одной группы разделов).

Подключение SQLite через FDConnection1 и FDQuery1. Тут нормально.

На Form1 лежит ListBox1 в него из таблицы kategorii добавлены данные NAM1 стандартным методом .

procedure TForm1.FormCreate(Sender: TObject);
begin
  try
    ListBox1.Items.Clear;
    FDQuery1.Close;
    FDQuery1.SQL.Clear;
    FDQuery1.SQL.Add('select * from kategorii');
    FDQuery1.OpenOrExecute;
    while not FDQuery1.Eof do
    begin
      ListBox1.Items.Add(FDQuery1.FieldByName('nam1').AsString);
      FDQuery1.Next;
    end;
  except   on e: exception do
    Showmessage(e.ClassName + ': ' + e.Message);
  end;
end;

В ListBox-e для примера Овощи, Фрукты, Страна, Звери.... 

Поле kateg имеет значения 1,2,3,4 соответственно. Вторая таблица для каждой категории из первой таб. имеет разделы : лук, чеснок,помидор, хрен...Поле KATEG2 для этих элементов равно 1.

Для фруктов то же четыре наименования и KATEG2=2. Остальное по такому же принципу. 

Есть вторая форма: на ней тоже ListBox, Button-с процедурой Form2.Hide и FDQuery2;

Необходимо: при процедуре TForm1.ListBox1ItemClick открывалась Form2 и в ListBox2 загружались данные относящиеся только к одной категории.

С формой проблем нет:

Form2.Show;Form2.FDQuery2.Close;
Form2.FDQuery2.SQL.Clear;
Form2.FDQuery2.SQL.Add('select razdel.NAM2 from razdel WHERE razdel.kateg2='+???????? 
Form2.FDQuery2.OpenOrExecute;

Вопрос: как получить значение поля kateg первой таблицы что бы во втором ListBox были данные относящиеся к нажатому в первом листбоксе пункта....

Делал все то же самое но вместо ListBox1 в Form1 использовал Grid1. В нем через переменную

 i:=FDQuery1.FieldByName('kateg').AsInteger ;
.......
Form2.FDQuery2.SQL.Add('select razdel.NAM2 from razdel WHERE razdel.kateg2='+IntToStr(i));

получал нужный результат и все работает, на телефоне выглядит нормально. Но меня этот вариант не устраивает. Нужно использовать ListBox на первой форме.Помогите!

post-1060-0-12817200-1429374677_thumb.jp

post-1060-0-57522600-1429374684.jpg

post-1060-0-54912900-1429374701.jpg

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Точно не знаю, но может лучше использовать ListView он по шустрее на мобиле, и как вариант предлагаю использовать вариант с передачей необходимых значений с помощью Tag

1. Загрузка первой таблицы:

 

{Form.Create } Загрузка первой страницы

FDQuery1.SQL.Clear;
FDQuery1.SQL.Add('select * from kategorii');
FDQuery1.OpenOrExecute;
ListView1.Clear;
ListView1.BeginUpdate;
for i:=0 to FDQuery1.RecordCount-1 do
     begin
        ListView1.Items.AddItem(i);
        ListView1.Items.Item(i).Text:=FDQuery1.FieldByName('nam1').AsString;
        ListView1.Items.Item(i).Tag:=FDQuery1.FieldByName('kateg').AsInteger;
        FDQuery1.Next;
     end;
ListView1.EndUpdate;

Загрузка второй таблицы

{ ListView1ItemClick(const Sender: TObject;  const AItem: TListViewItem) } Событие ItemClick на ListView1 передает объект ListView; оттуда и цепляем Tag;
Form2.FDQuery2.Close;
Form2.FDQuery2.SQL.Clear;
Form2.FDQuery2.SQL.Add('select razdel.NAM2 from razdel WHERE razdel.kateg2=Aitem.Tag; 
Form2.FDQuery2.OpenOrExecute;
И так же загружай в ListView2 (Шустрее работает с BeginUpdate и EndUpdate);
Изменено пользователем Brovin Yaroslav
Ссылка на комментарий
  • 0

Недавно в одном из проектов сделал так:

  1. Создал Data module
  2. На него перенес все компаненты FD*
  3. Созданный модуль прописал в uses нужных форм.
  4. Стало возможно обращаться к отобранным данным из одной формы в другой.
  5. В ListBox rowid и доп.информацию хранил в LisBox.Item(i).Tag и ListBox.Item(i).TagString (как в примере выше)

Т.е. в вашем случае (к примеру юниту data module дали имя DM) в форме Form1 обращаемся к первому селекту DM.FDQuery1. При клике по строке из Listbox1 отбираем данные в DM.FDQuery2 (параметры отбора через listbox.selected... или как в примере выше). Дальше открываем Form2, где уже работаем с подготовленным набором DM.FDQuery2.

Ну это если правильно понял суть Вашего вопроса.

Ссылка на комментарий
  • 0

Вопрос решил прибегнув к помощи еще одного FDQuery и ListBox1ItemClick обработал по иному

 
procedure TForm1.ListBox1ItemClick(const Sender: TCustomListBox;
const Item: TListBoxItem);
var
s:string;
i:integer;
begin
s:=ListBox1.Items[ListBox1.ItemIndex]; //тут находил значение ListBox1 в переменную
FDQuery2.Close;
FDQuery2.SQL.Clear;
FDQuery2.SQL.Add('select kateg from kategorii WHERE NAM1="'+s+'"'); // тут ее использовал
FDQuery2.OpenOrExecute;
i:=FDQuery2.FieldByName('kateg').AsInteger;// тут  получал номер категории из того поля которое явно в ListBox не попадает
Form2.Show;
Form2.FDQuery2.Close;
Form2.FDQuery2.SQL.Clear;
Form2.FDQuery2.SQL.Add('select razdel.NAM2 from razdel WHERE razdel.kateg2='+IntToStr(i));// далее в Form2 в ListBox выводил раздел относящийся к категории из первой формы
Form2.FDQuery2.OpenOrExecute;
end;
 
Zairkz, вариант с ListView посмотрю.
Прикреплю исходник того что получилось, база в архиве, все работает. Спасибо за советы, попытаюсь применить на практике. В принципе вопрос решен. 

ProjectListBoxSQLite.zip

Ссылка на комментарий
  • 0

Ну вот не удержался, извините.

Если бы Вы воспользовались советом zairkz, вам бы дополнительный seleсt не потребовался. Сразу же, при заполнение списка в ListBox сохраните kateg в поле Item(i).Tag

Тогда вся обработка в ListBox1ItemClick будет:

procedure TForm1.ListBox1ItemClick(const Sender: TCustomListBox;
const Item: TListBoxItem);
var
  //s:string;
  i:integer;
begin
  { убираем
  s:=ListBox1.Items[ListBox1.ItemIndex]; //тут находил значение ListBox1 в переменную
  FDQuery2.Close;
  FDQuery2.SQL.Clear;
  FDQuery2.SQL.Add('select kateg from kategorii WHERE NAM1="'+s+'"'); // тут ее использовал
  FDQuery2.OpenOrExecute;
  i:=FDQuery2.FieldByName('kateg').AsInteger;// тут  получал номер категории из того поля которое явно в ListBox не попадает
  }
  i := Item.Tag;   // или вообще без этой переменной
  Form2.Show;
  Form2.FDQuery2.Close;
  Form2.FDQuery2.SQL.Clear;
  Form2.FDQuery2.SQL.Add('select razdel.NAM2 from razdel WHERE razdel.kateg2='+IntToStr(i));// далее в Form2 в ListBox выводил раздел относящийся к категории из первой формы
  Form2.FDQuery2.OpenOrExecute;
end;

Красивый код постепенно из мелочей складывается  :wacko:

Ссылка на комментарий
  • 0

Ну вот не удержался, извините.

Если бы Вы воспользовались советом zairkz, вам бы дополнительный seleсt не потребовался. Сразу же, при заполнение списка в ListBox сохраните kateg в поле Item(i).Tag

Тогда вся обработка в ListBox1ItemClick будет:

procedure TForm1.ListBox1ItemClick(const Sender: TCustomListBox;
const Item: TListBoxItem);
var
  //s:string;
  i:integer;
begin
  { убираем
  s:=ListBox1.Items[ListBox1.ItemIndex]; //тут находил значение ListBox1 в переменную
  FDQuery2.Close;
  FDQuery2.SQL.Clear;
  FDQuery2.SQL.Add('select kateg from kategorii WHERE NAM1="'+s+'"'); // тут ее использовал
  FDQuery2.OpenOrExecute;
  i:=FDQuery2.FieldByName('kateg').AsInteger;// тут  получал номер категории из того поля которое явно в ListBox не попадает
  }
  i := Item.Tag;   // или вообще без этой переменной
  Form2.Show;
  Form2.FDQuery2.Close;
  Form2.FDQuery2.SQL.Clear;
  Form2.FDQuery2.SQL.Add('select razdel.NAM2 from razdel WHERE razdel.kateg2='+IntToStr(i));// далее в Form2 в ListBox выводил раздел относящийся к категории из первой формы
  Form2.FDQuery2.OpenOrExecute;
end;

Красивый код постепенно из мелочей складывается  :wacko:

 

Проблема в том, что этот вариант в моем случае не работает. i := Item.Tag при нажатии возвращает 0, а во второй форме ListBox становится пустой. прикладываю скрин с откомпелированной программой под win-32. Среда DELPHI XE7. На Form1 положил Label1 чтоб видеть значение i...оно равно 0. Спасибо за внимание к моему проекту, но этот метод или не полный или не подходящий. 

post-1060-0-12272800-1429546905_thumb.jp

Ссылка на комментарий
  • 0

 

Ну вот не удержался, извините.

Если бы Вы воспользовались советом zairkz, вам бы дополнительный seleсt не потребовался. Сразу же, при заполнение списка в ListBox сохраните kateg в поле Item(i).Tag

Тогда вся обработка в ListBox1ItemClick будет:

procedure TForm1.ListBox1ItemClick(const Sender: TCustomListBox;
const Item: TListBoxItem);
var
  //s:string;
  i:integer;
begin
  { убираем
  s:=ListBox1.Items[ListBox1.ItemIndex]; //тут находил значение ListBox1 в переменную
  FDQuery2.Close;
  FDQuery2.SQL.Clear;
  FDQuery2.SQL.Add('select kateg from kategorii WHERE NAM1="'+s+'"'); // тут ее использовал
  FDQuery2.OpenOrExecute;
  i:=FDQuery2.FieldByName('kateg').AsInteger;// тут  получал номер категории из того поля которое явно в ListBox не попадает
  }
  i := Item.Tag;   // или вообще без этой переменной
  Form2.Show;
  Form2.FDQuery2.Close;
  Form2.FDQuery2.SQL.Clear;
  Form2.FDQuery2.SQL.Add('select razdel.NAM2 from razdel WHERE razdel.kateg2='+IntToStr(i));// далее в Form2 в ListBox выводил раздел относящийся к категории из первой формы
  Form2.FDQuery2.OpenOrExecute;
end;

Красивый код постепенно из мелочей складывается  :wacko:

 

Проблема в том, что этот вариант в моем случае не работает. i := Item.Tag при нажатии возвращает 0, а во второй форме ListBox становится пустой. прикладываю скрин с откомпелированной программой под win-32. Среда DELPHI XE7. На Form1 положил Label1 чтоб видеть значение i...оно равно 0. Спасибо за внимание к моему проекту, но этот метод или не полный или не подходящий. 

 

А вот как оно в моем варианте:

post-1060-0-67235400-1429547189_thumb.jp

Ссылка на комментарий
  • 0

 

 

Проблема в том, что этот вариант в моем случае не работает. i := Item.Tag при нажатии возвращает 0, а во второй форме ListBox становится пустой.  

 

 

ну так вы просто Item.Tag не заполняете при выводе первого listbox.

если у вас будет 2 и более одинаковых наименования, то ваш код работать не будет!

Ссылка на комментарий
  • 0

 

 

 

Проблема в том, что этот вариант в моем случае не работает. i := Item.Tag при нажатии возвращает 0, а во второй форме ListBox становится пустой.  

 

 

ну так вы просто Item.Tag не заполняете при выводе первого listbox.

если у вас будет 2 и более одинаковых наименования, то ваш код работать не будет!

 

ListBox1 на первой форме заполняется из таблицы с тремя полями(ID,NAM1,kateg), поле NAM1 попадает в ListBox и значения там уникальные. Чем может быть заполнен Item.Tag при заполнении ListBox1 не представляю. Поле kateg с ListBox1 не связано. Я двумя руками за то чтоб этот код упростить, но красивый код не всегда работающий код...Подскажите как можно использовать конструкций i:=Item.Tag в TForm1.FormCreate.

Ссылка на комментарий
  • 0

 

 

 

Чем может быть заполнен Item.Tag при заполнении ListBox1 не представляю. Поле kateg с ListBox1 не связано. 

 

 

 

Item.Tag := DataSet.FieldByName('kateg').Value;

 

DataSet в проекте не использовал....Для связи SQLite через FireDAC использую FDConnection, FDQuery, FDPhysSQLiteDriverLink. Вы предлагаете добавить компонент DataSet? Или это свойство? Простите,я с БД пока на "ВЫ"...

Ссылка на комментарий
  • 0

 

 

 

Чем может быть заполнен Item.Tag при заполнении ListBox1 не представляю. Поле kateg с ListBox1 не связано. 

 

 

 

Item.Tag := DataSet.FieldByName('kateg').Value;

 

там на форме ListBox. Обращение немного другое. Сейчас картинку выложу

Ссылка на комментарий
  • 0

Способ рабочий. Часто применимый.

 

Вы не назначаете значение Tag, поэтому и считываете 0. Картинку с кодом и результатом прикладываю

Очень интересное решение, сейчас попробую..)))

Ссылка на комментарий
  • 0

Вообще, дружеский совет :-)

Почитайте про базы данных. В частности про язык SQL. Если в дальнейшем планируете писать программы с использованием  баз данных, в том числе и легких типа SQLite, узнаете много полезного. Про составные запросы и вьюхи. Правильно спроектированная структура таблиц, индексов, констрейнов и т.д. позволяет базе данных  жить "своей правильной жизнью". На тот же SQLite можно переложить часть заботы по поддержке целостности логической структуры. И код в итоге упрощается.

Удачи!

Ссылка на комментарий
  • 0

 

Способ рабочий. Часто применимый.

 

Вы не назначаете значение Tag, поэтому и считываете 0. Картинку с кодом и результатом прикладываю

Очень интересное решение, сейчас попробую..)))

 

Ну что тут сказать...Очень красиво. Все работает, поражает простота исполнения. Я об этом методе не знал. Спасибо большое!!!!

Ссылка на комментарий
  • 0

Думаю вы промахнулись, когда тыкнули "лучший ответ" на своем сообщении. Лучший ответ был пост №13 :)

Та да...Действительно проглядел)))) Что как отмечается, по не опытности понял по своему)))))Спасибо!!!

Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...