Продолжаем серию статей под общим названием «Firemonkey. От простого к сложному«. На повестке дня, как и было сказано в последней статье цикла, основы работы с таблицами в Firemonkey.
Наряду с таким компонентом как TLisBox, TLabel, TButton и т.д. таблицы по праву занимают одно из основных мест на палитре компонентов Delphi-разработчика. Если речь идёт о работе с базами данных, например, с SQLite, то тут на 99,9% случаев придётся использовать таблицы или же изобретать свой «велосипед» для вывода данных на форму. А раз так, то стоит обратить на эти компоненты первоочередное внимание и посмотреть на работу с ними в Firemonkey.
Содержание
[adsenseyu1]
Firemonkey предлагает нам на выбор два вида таблиц, которые расположены на вкладке Grids:
- TGrid — таблица с полями произвольного типа
- TStringGrid — таблица с текстовыми полями.
Оба эти компонента имеют общего родителя — TCustomGrid. Как понятно из названия, TStringGrid в Firemonkey — это, если правильно так выразиться, лишь частный случай таблицы как таковой и может содержать только текст. Некоторые моменты по работе с такими таблицами были рассмотрены в статье «SQLite и FireMonkey. Учимся заполнять таблицы.» До частных случаев и способах заполнения таблиц мы ещё дойдем, а пока сосредоточим свое внимание на работе с первым видом таблиц — TGrid.
Компонент TGrid — сетка.
В соответствии с основной идеей Firemonkey, согласно которой каждый компонент на форме — это контейнер для других элементов, TGrid представляет собой контейнер в котором можно разместить следующие FMX-объекты, являющиеся коллекциями строк:
- TColumn — столбец таблицы с неопределенным содержимым. Можно использовать для создания своих столбцов (с ComboBox’ами и другими элементами)
- TStringColumn — столбец, который будет содержать только строки
- TCheckColumn — столбец в котором будут размещаться чекбоксы
- TProgressColumn — столбец для отображения прогресса какой-либо операции
- TPopupColumn — столбец со списком выбора
- TImageColumn — столбец с картинками
Как видите, то ради чего мы в VCL шли на всякого рода ухищрения и переопределения методов стандартного компонента, лезли в дебри модуля Themes и т.д. в Firemonkey можно решить, определив столбец грида с определенным типом. Нужен текст — определили TStringColumn, надо картинку вставить — определили TImageColumn и т.д. Можно определить и свои типы столбцов, например, с ComboBox внутри. Однако, при первом взгляде на свойства, например, того же объекта TProgressColumn не совсем ясно как изменить текущий прогресс. Вроде бы есть свойства Min и Max, а привычного Position или Value нет, т.к. эти свойства (Value или Position) должны распространяться на ячейку, а не на весь столбец.
Чтобы разобраться с этим и другими вопросами по работе с таблицами в Firemonkey вначале рассмотрим свойства и методы непосредственно самого TGrid, а затем рассмотрим каждый объект столбца в отдельности и попробуем создать таблицу со всеми возможными вариантами столбцов — от самого простого TStringColumn до практически универсального TColumn.
Методы, свойства и события компонента TGrid
У компонента TGrid определены следующие свойства
Свойство | Описание свойства |
published-свойства | |
property AlternatingRowBackground: Boolean read FAlternatingRowBackground write SetAlternatingRowBackground default False; | Как и в случае с TListBox, в случае, если это свойство равно True каждая вторая строка таблицы будет раскрашена в другой цвет. |
property RowHeight: Single read FRowHeight write SetRowHeight; | Задает высоту строки таблицы |
property ShowSelectedCell: Boolean read FShowSelectedCell write SetShowSelectedCell default True; | True означает, что выбранная ячейка таблицы будет выделена (по умолчанию белым цветом) |
property ShowVertLines: Boolean read FShowVertLines write SetShowVertLines default True; | Показывает/убирает вертикальные линии таблицы |
property ShowHorzLines: Boolean read FShowHorzLines write SetShowHorzLines default True; | Показывает/убирает горизонтальные линии таблицы |
property ShowHeader: Boolean read FShowHeader write SetShowHeader default True; | Показывает/убирает заголовки столбцов таблицы |
property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False; | В случае True данные в таблице невозможно отредактировать |
public-свойства | |
property TopRow: Integer read GetTopRow; | Возвращает индекс строки, которая в текущий момент является самой верхней в видимой части таблицы |
property VisibleRows: Integer read GetVisibleRows; | Возвращает количество видимых строк таблицы, включая строку заголовков и не полностью видимые строки |
property ColumnCount: Integer read GetColumnCount; | Возвращает количество столбцов таблицы |
property ColumnIndex: Integer read FColumnIndex write SetColumnIndex; | Возвращает индекс выбранного столбца таблицы |
property Columns[Index: Integer]: TColumn read GetColumn; | Предоставляет доступ к столбцу таблицы с индексом Index |
property RowCount: Integer read FRowCount write SetRowCount; | Определяет общее количество строк таблицы |
property Selected: Integer read FSelected write SetSelected; | Определяет индекс выделенной строки таблицы |
Для компонента TGrid определены следующие публичные методы:
Метод | Описание метода |
function ColumnByIndex(const Idx: Integer): TColumn; | Возвращает объект столбца TColumn по его индексу Idx |
function ColumnByPoint(const X, Y: Single): TColumn; | Возвращает объект столбца TColumn по заданным координатам точки (X,Y) |
function RowByPoint(const X, Y: Single): Integer; | Возвращает индекс строки по заданным координатам точки (X,Y) |
procedure AddObject(AObject: TFmxObject); override; | Добавляет в контейнер TGrid новый произвольный объект AObject |
Событие | Описание события |
TOnGetValue = procedure(Sender: TObject; const Col, Row: Integer; var Value: Variant) of object; |
Событие можно использовать для заполнения ячеек таблицы. Col и Row содержат индексы столбца и строки соответственно, а Value — значение в ячейке, которое можно менять по своему усмотрению. |
TOnSetValue = procedure(Sender: TObject; const Col, Row: Integer; const Value: Variant) of object; |
Событие вызывается сразу после установки нового значения в ячейке таблицы. Значения параметров те же, что и у TOnGetValue |
TOnEdititingDone = procedure(Sender: TObject; const Col, Row: Integer) of object; |
Событие вызывается после того как значение в ячейке было изменено после OnSetValue |
Как видите из представленных выше таблиц, возможностей для работы с TGrid, что называется «из коробки», не так уж и много.
Пример использования свойств, методов и событий TGrid
В качестве небольшого примерчика к этой части статьи напишем небольшую программу, демонстрирующую работу с TGrid. Создадим новое приложение Firemonkey HD Application, бросим на главную форму приложения TGrid и несколько компонентов, представленных на рисунке ниже:
В начале поработаем немного с published-свойствами. Для этого в программе используются 6 CheckBox’ов, а также 1 Edit для установки высоты строки. В OnCreate формы напишем следующие строки:
procedure TForm16.FormCreate(Sender: TObject); begin cbAlternatingRowBackground.IsChecked:=Grid1.AlternatingRowBackground; cbShowSelectedCell.IsChecked:=Grid1.ShowSelectedCell; cbShowVertLines.IsChecked:=Grid1.ShowVertLines; cbShowHorzLines.IsChecked:=Grid1.ShowHorzLines; cbShowHeader.IsChecked:=Grid1.ShowHeader; cbReadOnly.IsChecked:=Grid1.ReadOnly; end;
Соответственно, клик по CheckBox’у включает/отключает определенную опцию. Например, клик по cbShowSelectedCell показывает или скрывает выделенную ячейку:
procedure TForm16.cbShowSelectedCellChange(Sender: TObject); begin Grid1.ShowSelectedCell:=cbShowSelectedCell.IsChecked; end;
Я не просто так решил вставить в пост изменение именно этого свойства (ShowSelectedCell). Дело в том, что ровно в этом месте Вы можете наблюдать первую проблему при работе с Grid’ами в Firemonkey. По логике вещей, перевод в False свойства должен привести к тому, что текущая выбранная ячейка не должна выделяться (по дефолту — белым цветом). На деле же простой перевод ShowSelectedCell в False ровным счётом ничего не дает — ячейка, которая была выделена ПЕРЕД изменением свойства так и остается выделенной белым цветом. Смотрите рисунок ниже — свойство стоит в False, а курсор установлен в самую нижнюю видимую на экране ячейку:
Более того, попробуйте снова включить ShowSelectedCell, выделить ячейку где-нибудь в центре таблицы, потом установить ShowSelectedCell снова в False и поперемещать ScrollBar таблицы — увидите продолжение проблемки — в том месте, где была выделенная ячейка будет белое пятно =). Смотрите на рисунок:
В связи с представленными выше скринами возникает закономерный вопрос: как в TGrid гарантированно убрать выделенную ячейку? Причём так убрать, чтоб не было никаких артефактов и белых пятен?
Один из способов (не самых скоростных) — обновить стиль таблицы сразу же после изменения свойства ShowSelectedCell. В общем, написать, что-то типа такого:
procedure TForm16.cbShowSelectedCellChange(Sender: TObject); begin Grid1.ShowSelectedCell:=cbShowSelectedCell.IsChecked; Grid1.UpdateStyle; end;
Но сразу приготовьтесь к заметному снижению производительности — UpdateStyle у меня занимает по времени 4-5 секунд (!) о чем говорит лог CodeSite:
Так что совет №1: не меняйте лишний раз (без крайней необходимости) свойства таблицы в run-time — себе дороже выйдет. Лучше их сразу определять в design-time и потом спокойно работать.
С остальными published-свойствами у TGrid подобную проблему я заметил только в ReadOnly — тоже после изменения свойства на True последняя выделенная ячейка всё равно остается почему-то доступной для редактирования. Поэтому двигаемся далее. Public-свойства также были проверены на предмет непредвиденного поведения — никаких проблем не заметил. Другое дело — работа с данными в таблице TGrid. Вот уж где собака порылась так это в данных таблицы.
Прежде всего зададимся простой целью — заполнить нашу TGrid данными. Неважно какими — можно простыми строками, можно поустанавливать флажки в CheckBox’ах. Не в этом суть. Судя по имеющимся у TGrid свойствам, вроде бы самым оптимальным было бы воспользоваться обработчиком события OnGetValue. Что может быть проще?
Как было сказано выше (при рассмотрении событий TGrid) для таких целей можно использовать OnGetValue. Например, если таблица содержит два столбца первый из которых TStringColumn, а второй TCheckColumn, то обработчик OnGetValue мог бы выглядеть, например, вот так:
procedure TForm16.Grid1GetValue(Sender: TObject; const Col, Row: Integer; var Value: Variant); begin case Col of 0:Value:='Hello World'; 1:Value:=(Row mod 2) = 0; end; end;
При этом, в работающем приложении наша табличка выглядела бы вот так:
И всё бы ничего, НО теперь вы не сможете просто так взять и изменить значения в таблице. Нет вы, конечно же, можете установить курсор в любую ячейку и сделать всё, что душе угодно, например, вместо Hello World написать Good Bye и т.д. — это сработает, но до первой перерисовки таблицы, после чего таблица в соответствии с тем, что написано в обработчике, примет свой первоначальный вид. Не будет ничего в обработчике — таблица очиститься. Вот такой вот «замес». Смотрим:
Не удивляйтесь, что видео снято с Mac OS, просто под рукой была запущенная виртуалка, а на VMware видео снять — раз плюнуть. Суть совершенно в другом. Непонятно какого лешего срабатывает OnGetValue по поводу и без повода? Дёрнул скрол — сработал обработчик, ткнул заголовок — опять сработал. Так и заработаться можно… Если проводить параллель между FMX и VCL, то у StringGrid’a в VCL имеется подобное событие, которое носит название OnGetEditText. Только у StringGrid’а параметр Value, как и полагается, имеет тип string. Так вот в VCL событие срабатывает именно тогда, когда мы получаем значение из ячейки — можете проверить и перенести код представленный выше в VCL-приложение — при запуске программы заполнение таблицы не произойдет, а вот, когда вы выделите ячейку таблицы — вот тогда код сработает.
Что в этом случае делать с табличкой TGrid в FMX и как её заполнять так, чтобы данные не потерялись после первого чиха? У меня пока на этот счёт крутится в голове вариант решения с использованием LiveBindings или вручную привязывать свою табличку к источнику данных, после чего в обработчике OnGetValue выдавать в Value необходимое значение из источника. Какая при этом будет производительность…не знаю — надо будет проверять, тестить. Совсем не исключено, что я где-то чего-то недопонимаю в работе с TGrid, но склоняюсь к мысли, что без детального изучения LiveBindings с таблицами да и вообще со списками будет очень тяжко работать.
Надо, кстати, сказать, что в FMX.TStringGrid подобной проблемы нет — данные из ячеек не пропадают….да там и OnGetValue нету….
Ну да ладно. О том как удобно и быстро заполнять TGrid’ы мы, думаю, ещё не раз поговорим в блоге или на форуме в специально созданном разделе, а пока посмотрим как можно использовать методы TGrid.
Чтобы продемонстрировать работу методов рассмотрим в нашей программке такой вопрос: как в один клик мышкой отметить или снять флажок в столбце TCheckColumn?
Сейчас для того чтобы отметить чекбокс мы должны первым кликом выделить ячейку, а уже вторым отметить чекбокс…не совсем удобно. Воспользуемся двумя методами TGrid и событием OnMouseMove:
procedure TForm16.Grid1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); begin if Assigned(Grid1.ColumnByPoint(X,Y)) then Grid1.ColumnIndex:=Grid1.ColumnByPoint(X,Y).Index; Grid1.Selected:=Grid1.RowByPoint(X,y) end;
В работающей программе этот код будет приводить к следующим действиям:
[youtube_sc url=»eqlCIqDdW8Y» title=»Авто-выделение%20ячеек%20в%20таблице%20TGrid»]Здесь я использовал два метода TGrid с помощью которых определил в какой ячейке таблицы в данный момент находится мышка и с помощью свойств ColumnIndex и Selected выделил эту ячейку. Здесь вроде бы никаких неожиданностей не возникло.
На этой оптимистической ноте примерчик оставим на немного в покое. И перейдем к следующей части — рассмотрим типы столбцов, которые есть у TGrid.
Столбцы TGrid
Как я говорил выше, для TGrid определены в Firemonkey следующие объекты столбцов:
- TStringColumn
- TCheckColumn
- TProgressColumn
- TPopupColumn
- TImageColumn
Все эти объекты имеют общего родителя — TColumn. В TColumn содержатся свойства и методы для работы с любыми объектами столбцов TGird будь то TStringGridColumn, TImageColumn или объект столбца с произвольным содержимым. Давайте вначале рассмотрим, что из себя представляет объект TColumn.
TColumn
Свойства и методы TColumn
Как Вы знаете из VCL, да и просто из жизни — каждый столбец таблицы может содержать произвольное количество ячеек, в которые заносятся данные. В связи с тем, что в FMX каждый объект — это контейнер для других объектов, в таблицах Firemonkey методы работы с ячейками содержатся именно в объектах столбцов, а не в самом классе TGrid.
TGrid изначально «не знает», что Вам вздумается заносить в ячейки — текст, картинку, компонент Switch или ещё что-то. Всё, что знает TGrid — это набор столбцов. А вот TColumn (а точнее потомок TColumn) — может и знает, что в нем есть набор ячеек, т.к. именно наследник TColumn — является контейнером для этих объектов.
В TColumn определены следующие общие для всех столбцов свойства:
Свойство | Описание свойства |
property Header: string read FHeader write SetHeader; | Содержит название заголовка столбца |
property ReadOnly: Boolean read FReadOnly write FReadOnly default False; | True означает, что содержимое столбца только для чтения |
Для управления содержимым столбца в TColumn определены следующие методы:
Метод | Описание метода |
function CellControlByPoint(X, Y: Single): TStyledControl; | Возвращает объект ячейки, координаты которой содержат точку (X,Y). Удобно использовать, например, для определения ячейки над которой в данный момент находится курсор мыши |
function CellControlByRow(Row: Integer): TStyledControl; | Возвращает объект ячейки по индексу Row строки |
Обратите внимание, что оба этих метода, опять же в соответствии с концепцией Firemonkey, ничего не знают про тип ячейки и возвращают лишь TStyledControl. Для того, чтобы начать работу со столбцом и знать какие данные можно записывать в его ячейки, в TColumn определен следующий защищенный виртуальный метод:
function CreateCellControl: TStyledControl; virtual;
Для каждого типа столбца этот метод переопределяется и, соответственно, благодаря этому мы можем узнать какую ячейку мы получили. Например, в TColumn метод CreateCellControl выглядит следующим образом:
function TColumn.CreateCellControl: TStyledControl; begin Result := TTextCell.Create(Self); TTextCell(Result).OnTyping := DoTextChanged; TTextCell(Result).OnExit := DoTextExit; end;
Как видите, в этом методе создается объект ячейки для хранения текстовых данных (TTextCell). Если посмотреть на TTextCell, то мы увидим, что это ни что иное как наследник от TEdit:
TTextCell = class(TEdit) end;
Аналогичным образом выглядят и другие типы ячеек:
TCheckCell = class(TCheckBox) end; TProgressCell = class(TProgressBar) end; TPopupCell = class(TPopupBox) end; TImageCell = class(TImageControl) end;
Таким образом, получив с помощью метода CellControlByPoint/CellControlByRow ячейку мы можем определить её класс и в зависимости от того какой объект является ячейкой — подобрать соответствующие данные для записи, изменить свойства родителя ячейки и т.д. Ну, например, рассмотрим такой вопрос: как в ячейку столбца TCheckColumn добавить текст?
Сделать это довольно просто. Если наша ячейка содержится в столбце с индексом Col и строке с индексом Row, то добавление текста в эту ячейку можно организовать, например, так:
(Grid1.ColumnByIndex(Col).CellControlByRow(Row) as TCheckCell).Text:='WebDelphi.ru';
В запущенном приложении ячейка TCheckCell будет выглядеть так:
Ну и, конечно же, никто не мешает вам менять и другие свойства родительского объекта — изменять цвет, состояние, добавить анимацию, связывать объект ячейки с данными при помощи LiveBindings и т.д.
Теперь, когда мы более менее рассмотрели вопрос о том, как происходит работа со столбцами и ячейками на примере TColumn, мы можем рассмотреть, что содержится в наследниках TColumn и как с ними работать.
TCheckColumn
Объект столбца каждая ячейка которого содержит CheckBox.
Тип ячейки: TCheckCell
Метод CreateCellControl у TCheckColumn переопределен следующим образом:
function TCheckColumn.CreateCellControl: TStyledControl; begin Result := TCheckCell.Create(Self); Result.StyleLookup := 'checkboxstyle'; TCheckCell(Result).OnChange := DoCheckChanged; end;
Соответственно, при изменении состояния CheckBox’а срабатывает метод DoCheckChanged, в котором последовательно выполняются события: OnSetValue и OnEdititing. О том, как заполнить таблицу данными с помощью обработчика OnGetValue рассказано чуть выше.
TStringColumn
Объект столбца, содержащего текст.
Тип ячейки: TTextCell.
У TStringColumn отсутствует переопределенный метод CreateCellControl, т.к. тип ячейки у TColumn и TStringColumn совпадает — переопределять ничего не требуется.
TProgressColumn
Объект столбца каждая ячейка которого содержит ProgressBar.
Тип ячейки: TProgressCell
Метод CreateCellControl у TProgressColumn переопределен следующим образом:
function TProgressColumn.CreateCellControl: TStyledControl; begin Result := TProgressCell.Create(Self); TProgressCell(Result).Min := FMin; TProgressCell(Result).Max := FMax; end;
TProgressColumn содержит два новых свойства для управления границами ProgressBar’ов:
property Min: Single read FMin write FMin; property Max: Single read FMax write FMax;
Пример настройки столбца и заполнения ячеек представлен ниже:
ProgressColumn1.Min := 0; ProgressColumn1.Max := 25; (ProgressColumn1.CellControlByRow(1) as TProgressCell).Value := 15;
В запущенном приложении это будет выглядеть следующим образом:
TPopupColumn
Объект столбца каждая ячейка которого содержит Popup-меню.
Тип ячейки: TPopupCell
Метод CreateCellControl переопределен следующим образом:
function TPopupColumn.CreateCellControl: TStyledControl; begin Result := TPopupCell.Create(Self); TPopupCell(Result).Items.Assign(FItems); end;
Так как каждая ячейка в столбце — это PopupBox, то при создании ячейки её родитель получает набор строк для формирования пунктов меню. Отсюда и новое свойство столбца:
property Items: TStrings read FItems write SetItems;
То есть, чтобы воспользоваться столбцом TPopupColumn мы вначале должны заполнить его свойство Items. В запущенном приложении ячейки типа TPopupCell выглядят следующим образом:
TImageColumn
Объект столбца в котором каждая ячейка может содержать изображение.
Тип ячейки: TImageCell
Метод CreateCellControl переопределен следующим образом:
function TImageColumn.CreateCellControl: TStyledControl; begin Result := TImageCell.Create(Self); TImageCell(Result).EnableOpenDialog := False; end;
Примером работы с TImageCell может служить следующий код:
procedure TForm16.Button5Click(Sender: TObject); var cc: TImageCell; begin if OpenDialog1.Execute then begin cc:=ImageColumn1.CellControlByRow(1) as TImageCell; if Assigned(cc) then cc.Bitmap.LoadFromFile(OpenDialog1.FileName); end; end;
Результатом выполнения этого кода станет, например, вот такая картинка в таблице:
Как видите, работа с ячейками в таблице ничем не отличается от работы с любыми другими компонентами Firemonkey. Любая ячейка в таблице — это какой-либо известный компонент (TEdit, TPopupBox, TProgressBar и т.д). Следовательно, никто нам не запрещает, используя TColumn создать свой собственный столбец таблицы со своим компонентом внутри ячейки.
Столбцы TGrid своего типа.
Итак, рассмотрим вопрос: как создать столбец в таблице каждая ячейка которого будет содержать необходимый нам компонент. Вопрос довольно актуальный ещё со времен, когда в Delphi была только VCL. Даже сейчас форумы по Delphi пестрят вопросами типа «Как в StringGrid вставить CheckBox?» или «Как в StringGrid вставить ComboBox?» и т.д. В отношении таких вопросов Firemonkey оказывается значительно проще в использовании нежели её «старшая сестра» — VCL.
Ну, например, мы хотим сделать красивую таблицу в которой есть столбец с переключателями. CheckBox’ы уже как-то приелись — хочется чего-нибудь по-красивее. В Firemonkey есть специальный компонент, который так и называется — TSwitch. Давайте встроем его в нашу таблицу TGrid.
Рассмотрим весь процесс создания такой колонки таблицы по порядку.
1. Создаем класс для новой ячейки. Назовем его TSwitchCell:
type TSwitchCell = class(TSwitch) end;
2. Создаем наследника TColumn и перекрываем у него метод CreateCellControl
type TSwitchColumn = class(TColumn) private function CreateCellControl: TStyledControl; override; public constructor Create(AOwner: TComponent); override; end;
3. Добавляем новый столбец к своей таблице
Grid1.AddObject(TSwitchColumn.Create(Grid1));
Всё. В запущенном приложении наша таблица будет выглядеть вот так:
Не устраивает как выглядит ячейка с TSwitch, когда бегунок стоит в крайнем левом положении? Создайте свой или переопределите существующий стиль для этого компонента. Дефолтный стиль носит название switchstyle.
Компонент TStringGrid
Этот компонент напоминает уже известный нам из VCL компонент TStringGrid. Так как таблица FMX.TStringGrid предназначена исключительно для хранения строк, то в это компоненте реализовано ещё одно свойство, упрощающее доступ к ячейкам:
property Cells[ACol, ARow: Integer]: string read GetCells write SetCells;
Про то, как работать с TStringGrid в Firemonkey я рассказывал в отдельном посте.
В связи с тем, что в StringGrid мы точно знаем, что любая ячейка содержит текстовые данные, то именно этот компонент можно использовать для удобного вывода данных из БД в программу. Пример связывания базы данных и FMX.TStringGrid есть в примерах Delphi XE2. Пример находится в директории:
c:\Users\Public\Documents\RAD Studio\9.0\Samples\LiveBindings\binddblink\fmx\
На сегодня разговор про таблицы в Firemonkey закончим. Думаю, что информации для начинающих разбираться с новой платформой окажется достаточно, чтобы понять основы работы. В дальнейшем мы ещё вернемся к TGrid и TstringGrid, чтобы рассмотреть их работу более детально.
хорошая статья, спасибо
Влад, я тут хочу предложить более лучший вариант отметки галки CheckBox’а за один клик мышки:
if Grid1.Columns[Grid1.ColumnIndex].ClassType = TCheckColumn then
(Grid1.Columns[Grid1.ColumnIndex].CellControlByRow(Grid1.Selected) as TCheckCell).IsChecked := not (Grid1.Columns[Grid1.ColumnIndex].CellControlByRow(Grid1.Selected) as TCheckCell).IsChecked
Предложенный тобой метод немного некорректный — во время клика по ячейке не факт, что происходит смена флага (то срабатывает, то нет).
В предложенном мной способе мы меняем флажок на инвертный, если выделенная ячейка находится в столбце типа TCheckColumn.
Хотя я предполагаю, что должно быть какое-то простое свойство, отвечающее за двойной или одинарный клик-смену флага в Checkbox-ячейке
Кстати, по поводу:
(Grid1.ColumnByIndex(Col).CellControlByRow(Row) as TCheckCell).Text:=’WebDelphi.ru’;
Заметил, что отрабатывает без ошибок только видимых строк (ячеек). Если меняем ячейку вне области видимости, то код срабатывает, но с ошибкой. Может кто знает, почему и как этого избежать?
Спасибо за статью.
По поводу того что OnGetValue дергается при каждой перерисовке — это абсолютно нормально и правильно, нечего данные хранить в визуальных контролах. Если вы когда нибудь с VirtualStringTree работали то должны знать о чем речь.
создаю колонку свое типа, но стиль к ней не применяется. даже когда присваю StyleLookup на CreateCellControl ( фон остается белым
Полезная статья, спасибо. У меня вопрос: можно ли добавить обьект (пусть будет тот же прогресс бар) в отдельную ячейку? В vcl можно было так
StringGrid1->object[acol][arow]=progressbar;
в fmx я что-то так и не понял как сделать
На XE3 не выходит, CellControlByRow — вообще нету…
Виталя, не удивительно — FMX 2.0. очень сильно переписали
Жаль конечно. Влад не могли бы вы показать как FMX 2.0 добавить например кнопку в Grid или хотя бы на толкнуть на мысль, а то как кроме создания TButton по координатам сетки, на ум не приходит…
О том как работать с ячейками гридов писал Андрей Терехов тут — http://teran.karelia.pro/articles/item_4502.html. Статья относится к FMX 1, но то, что там написано работает до сих пор
Спасибо посмотрю статью, еще пришла мысль попробовать создать стиль с нужными мне элементами и подключить его через StyleBook
Виталя, врядли просто так удастся перелопатить стиль грида и применить его. Но, как говориться, попытка — не пытка :)
исходник в студию)
дык…исходник FireMonkey как бы уже присутствует в Delphi =) Или какой вас исходник интересует?
не могу разобраться с (Grid1.ColumnByIndex(Col).CellControlByRow(Row) as TCheckCell).Text:=’WebDelphi.ru’; ругается CellControlByRow(Row) Что и где нужно объявлять?
Может у Вас таже проблема, что и у предыдущего комментатора? Или у вас FMX 2.0 и метод отсуствует? Исходник накидать по новой не трудно, просто хотелось бы посмотреть, что за ошибка при обращении к методу.
))) все верно. у меня тоже xe3. видимо этот метод в fmx2 имеет другое название
irina, да, в XE3 много чего поменялось. Настолько много, что хоть бери и переписывай все посты про FMX 1.0 :)….
Hi Vlad
do you know how to change the background color of a row, on a value in TGrid?
I use delphi XE5.
Для того, чтобы изменённые данные не пропадали «после первого чиха», нужно, чтобы эти данные сохранялись в какой-либо структуре и брались из неё же. Для данного примера это может быть массив записей. Например:
var arr: array of records
text: string;
checked: boolean;
end;
тогда текст процедуры OnGetValue может выглядеть так:
begin
case Col of
0: Value:=arr[col].text;
1: Value:=arr[col].checked;
end;
end;
и также необходимо в процедуре OnSetValue прописать обратные присвоения:
begin
case Col of
0: arr[Row].text := Value.AsString;
1: arr[Row].checked := Value.AsBoolean;
end;
end;