SQLite и FireMonkey. Учимся заполнять таблицы.Источник: webdelphiru Vlad
С появлением в Delphi XE2 FireMonkey иногда ощущаю себя прям каким-то первоклассником =) Не сказать, чтобы прям уж так совсем все непонятно и сложно...скорее немного не привычно использовать новые FMX-контролы. Вот и сегодня от темы статьи так и напоминает что-то из разряда "Delphi для начинающих". Но, как говориться, из песни слов не выкинешь - раз решил поработать с FireMonkey, то начинать надо с простых вещей. Ну, а так как в статье про SQLite для Delphi XE2 было предложение расписать работу с Grid'ами в FMX, то попробуем написать небольшое приложение, которое будет заполнять табличку на основании запроса к базе SQLite. И в начале несколько слов про SQLite в Delphi, а точнее про ту обертку с которой я буду работать. Дело в том, что это, наверное, самая простая обертка из всех, что мне встречались (собственно этим она мне и понравилась). Здесь нет компонентов, все объекты в модуле SQLiteTable3 - это классы-наследники от TObject, а вся работа напрямую связана с запросами к библиотеке SQLite (в Win-приложениях - это будет sqlite3.dll). Естественно, такая организация работы с SQLite накладывает некоторые ограничения на работу с БД SQLite. Например, я не могу взять и без лишних заморочек использовать TDataSet или использовать также просто как и при работе, например, с MSSQL DBGrid - придется искать свое решение, использовать TClientDataSet'ы и т.д. Но, мне такие решения в принципе не нужны были. Единственный раз когда мне приходилось использовать TDataSet, TDBGrid и т.д. был лет эдак пять-семь назад и то всё это "творчество" тогда использовало BDE. В общем, если у кого-то возникнет желание/потребность связать эту обертку с TDataSet - знайте, что сделать это просто и быстро врядли получится. Ну, а я рассмотрю пример того, как, используя SQLiteTable2.pas можно формировать таблицы в приложении Firemonkey. В качестве примера, воспользуемся базой данных, в которой будет содержаться таблица, рассмотренная в предыдущей статье про SQLite: CREATE TABLE [TestTable] ( Теперь посмотрим, что нам необходимо знать для того, чтобы заполнить таблицу. Для того, чтобы заполнить таблицу на форме (не важно какую - из FMX или VCL) нам необходимо знать помимо значений полей набора данных ещё как минимум два значения: количество полей (столбцов) и количество записей (строк) в таблице. Иначе мы просто не сможем правильно установить количество строк и столбцов у нашего контрола на форме. Для того, чтобы работать с самой БД мы должны знать какие таблицы в ней присутствуют. Для примера создадим новое приложение "Firemonkey HD Application" и разместим на форме следующие элементы: При нажатии на кнопку "Connect" мы будем подключаться к базе данных и считывать из неё названия всех таблиц. Я предложил использовать БД из предыдущей статьи, но фактически приложение сможет работать с любой указанной вами БД, поэтому списочек получать мы будем так: uses type Здесь стоит отметить следующие моменты. Во-первых, что за таблица sqlite_master к которой я так смело обратился? Это специальная таблица, которая содержится в любой БД SQLite и содержит сведения по базе данных. В моем случае я выбрал из sqlite_master только те записи, в которых содержатся сведения по таблицам БД, т.е. проверил значение поля type на присутствие в нем значения "table". Можно было бы запросить и всю таблицу целиком. sqlite_master выглядит следующим образом: CREATE TABLE sqlite_master ( Более подробно про эту таблицу можно почитать в официальном FAQ. Во-вторых, стоит немного рассказать про метод GetTableStrings у TSQLiteDatabase. Дело в том, что не важно какого содержания SELECT вы отправите к базе данных, этот метод всегда вернет строковые значения из первого столбца (с индексом 0). Ну, а так как у меня результат запроса и содержит всего одно поле, то я без лишних проверок записал все значения в ComboBox. Следующий момент - это отправка запроса к произвольной таблице БД. Здесь все довольно просто. Например, на OnChange ComboBox'а можно написать такой код: TableName:=; То есть после выбора названия таблички в ComboBox'е просто считываем все значения. Ну, а теперь подходим к главному. Получили мы все, что хотели из БД, а как теперь эти значения "вытянуть" на наш StringGrid? Вот здесь мы сделаем небольшое отступление от работы над приложением и проясним некоторые моменты по поводу FMX. StringGrid в FireMonkey Помните в начале статьи я сказал, что работать с контролами в FMX мне несколько непривычно? Про это я немного говорил в "Знакомстве с FireMonkey", теперь же постараюсь рассказать более подробно. Итак, раз вы (и я с вами) решили использовать в проекте FireMonkey, то первое, что стоит для себя уяснить - это то, что несмотря на схожесть названий контрол в FMX - это вообще не тоже самое, что контрол в VCL. У них общего столько же сколько у мопеда и мотоцикла Harley Davidson - оба на двух колесах. Например, все, что общего у двух TButton - это родитель TComponent. В FMX любой компонент - это контейнер. Контейнер может содержать в себе ещё один контейнер, а в том ещё 5 контейнеров и т.д. и при этом чем сложнее контрол - тем сложнее иерархия объектов. Все компоненты FMX собираются из базовых элементов, таких как TLayout, TRectangle и т.д. Вот она та самая "необычность" к которой надо привыкать в случае работы с FireMonkey. Теперь, что касается StringGrid в FMX. Чтобы разобраться из чего состоит таблица обратимся к StyleBook. Бросаем на форму компонент TStyleBook, дважды кликаем по нему мышкой и в дереве ищем запись gridstyle: Как видите в таблице FMX заголовок таблицы (header) и основное содержимое (content) - это разные элементы. То есть мы можем изменять стиль заголовков, не затрагивая при этом стиль строк таблиц. Но до этого нам пока ещё рано - надо разобраться как вообще управляться с таблицей. Для того, чтобы добавить в таблицу новый столбец, достаточно дважды кликнуть по таблице на форме и в редакторе нажать кнопку AddItem. Например, на рисунке ниже представлен редактор в котором я добавил в таблицу пять столбцов и вид окна Structure, чтобы дать вам небольшое предстовление о том, что в итоге получится, так сказать "концепция контейнеров в действии": Можно через тот же редактор сделать и так, что каждый столбец таблицы будет содержать в себе ещё с десяток столбцов, но в визуальном плане это никак не отразиться - таблица в приложении так и будет двухмерная. Для каждого столбца таблицы мы можем задать свои особые свойства, например, для нас сегодня будет важно свойство Header:string - заголовок столбца. Что касается ячеек таблицы, то каждый столбец (TStringColumn) содержит поле FCells, которое представляет собой массив строк. Свойства для этого поля нет, а вся работа с ячейками и строками осуществляется в родителе, т.е. с TStringGrid. И здесь отличий никаких в названиях свойств и методов от VCL нет. Например, чтобы указать количество строк, надо указать значение свойства RowCount: MyStringGrid.RowCount:=10; А чтобы указать значение для ячейки, воспользоваться свойством Cells: MyStringGrid.Cells[0,0]:='Ячейка 0,0' При этом помните, что заголовок таблицы и содержимое таблицы - разные элементы (см. структуру компонента выше). То есть значение индексов строк в VCL и FMX.StringGrid'ах будут различаться на 1 (см. рисунок ниже): Двигаемся далее. Раз решал рассмотреть свойства, то стоит отметить, что у FMX.StringGrid нет свойства ColCount для изменения количества столбцов в runtime. Вместо него есть свойство только для чтения под названием ColumnCount. Но это отнюдь не означает, что мы не в состоянии поменять количество столбцов у FXM.StringGrid в runtime. Сделать это можно, например так: //удаляем все столбцы из таблицы В целом это все особенности, которые нам необходимо уяснить для дальнейшей работы с FMX.StringGrid. Резюмируем и двигаемся обратно в наше приложение: Краткий экскурс в FMX.StringGrid закончили - продолжим работу над приложением. Нам осталось только правильно заполнять табличку и научить программу выполнять произвольные запросы. Начнем с таблицы и напишем метод, с помощью которого будет строится таблица с данными из запроса:
Здесь мы вначале определяем сколько столбцов надо добавить/удалить из таблицы. Затем приводим таблицу в исходное состояние, т.е. устанавливаем необходимое количество столбцов и строк. И наконец, проходимя по каждой записи в TSQLiteUniTable выводим значения полей в соответствующие ячейки FMX.StringGrid. Теперь остается только "навесить" необходимое событие на кнопку "Выполнить SQL" и вызвать только что созданный метод. Обработчик OnClick кнопки будет следующим: FStmt:=TSQLitePreparedStatement.Create(FBase); Ну и в заключение вид приложения в котором показана таблица FMX.StringGrid, содержащая ту самую 1000 записей, которые мы добавляли в прошлый раз: На отрисовку таблички ушло чуть больше 1 секунды. Исходник приложения (без DLL и базы данных) можно скачать по ссылке ниже: |