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

Как получить доступ к свойству объекта в стиле и как повесить свой обработчик на его события?


Kikoma

Вопрос

Здравствуйте, подскажите направление решения следующей проблемы:

 

Есть стилизовнный ListBoxItem, содержащий два поля:

  1. TText: [styleName = 'TextPrice' и 'TextSum']
  2. TSpinBox: [styleName = 'Count']

Каким образом:

  1. Можно повесить обработчик на SpinBox.OnChange, чтобы рассчитывать Sum?
  2. И как обратиться к значению SpinBox.Text?

Код обработчика события изменения SpinBox:

procedure TFormMain.SBCountChange(Sender: TObject);  //  Какой вызов и где его назначить?
var
  Item: TListBoxItem;
begin
  Item:=  ???  //Определение того итема, в котором был изменен TListBox [Name=StyleName='SBCount']
  Item.StylesData['TextSum'] := StrToInt(  Item.StylesData['TextPrice'] ) * StrToInt(  ??? SBCount.Text );
end

Подскажите, пожалуйста, а то только туманные решения

Изменено пользователем Brovin Yaroslav
Ссылка на комментарий

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

  • 0
  • Администраторы

Добрый день

О том, как получить доступ к любому свойству через StylesData (в том числе к свойству text) частично описано тут:

  1. Как получить значение свойства объекта стиля, используя StylesData?
  2. Как получить объект стиля?
  3. Назначение обработчиков событий для элементов стиля через StylesData

Допустим, что TSpinBox в стиле назван (StyleName), как 'spinbox', тогда

  • Присваивание обработчика для SpinBox:
    ListBoxItem1.StylesData['spinbox.OnChange'] := TValue.From<TNotifyEvent>(SBCountChange);
    
  • Доступ к свойству Text у TSpinBox:
    ListBoxItem1.StylesData['spinbox.Text'].ToString;

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

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

1. Обработчик заработал, спасибо.

единственной загадкой остался синтаксис '<TNotifyEvent>'  из

ListBoxItem1.StylesData['spinbox.OnChange'] := TValue.From<TNotifyEvent>(SBCountChange);

2. Как определить Item, из которого был вызван обработчик?

Как в самом Item добраться до объектов заданными по стилю - я понял, а сам Item как определить?

procedure TForm2.SBCountChange(Sender: TObject);
var
  Item: TListBoxItem;
begin

    Item:= ???????????; //Определяем Item, в котором есть SpinBox, который в свою очередь вызвал эту обработку
    
    //Получив Item делаем с ним что захотим, в том числе и обращаемся к объектам под StyleData
    
   ShowMessage('Item.tag='+IntToStr(Item.tag)); 
end;
Ссылка на комментарий
  • 0

После многих эксперементов вопрос решен следующим кодом:

procedure TForm2.SBCountChange(Sender: TObject);
var
  Item: TListBoxItem;
  SB: TSpinBox;
  s1, s2: string;
begin
  SB := Sender as TSpinBox; // Получили Sender из TSpinBox
  if Assigned(SB) and (SB is TSpinBox) then 
  begin

    Item := (((((SB.Parent).Parent).Parent).Parent).Parent) as TListBoxItem; //Соответствует структуре стиля

    s1 := StringReplace(Item.StylesData['TextPrice'].ToString,'.',',',[rfReplaceAll, rfIgnoreCase]);  //Тут обертка точку на запятую меняю
    s2 := StringReplace(Item.StylesData['SBCount.Text'].ToString,'.',',',[rfReplaceAll, rfIgnoreCase]);
    Item.StylesData['TextSum.Text'] := IntToStr(Round(StrToFloat(s1) * StrToInt(s2)));
  end;
end;

По поводу  (((((SB.Parent).Parent).Parent).Parent).Parent) as TListBoxItem; у меня структура Стиля несколько вложенных TRectangle для автоматического выравнивания, поэтому пришлось из каждого идти выше аж 5 раз.

 

Не претендую на идеальное решение, но работает отлично

 

Кстати, в стиле при использовании TPanel  вместо TRectangle StyleData['StyleName'] не работало. Поменяв TPanel на TRectangle все стало работать.

 

Коментарии приветствуются.

Вопрос решен

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

Ох, обалдеть =))) Вы прикинули сколько машинного времени на это уходит ? =))) Используйте лучше свойство "Tag" при создании item'a, если хотите примитива. Но то, что Вы написали - жестко =)

 

P.S. при создании listboxitem записывайте его индекс в поле Tag объекта TSpinBox. Как то так:

...
SB := Sender as TSpinBox; // Получили Sender из TSpinBox
if Assigned(SB) and (SB is TSpinBox) then 
begin
  Item := ListBox1.ItemByIndex(SB.Tag) as TListBoxItem;
...

И естественно не забывать при удалении item'a (item'ов) редактировать поля Tag у остальных TSpinBox

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

 

Ох, обалдеть =))) Вы прикинули сколько машинного времени на это уходит ? =))) ... Но то, что Вы написали - жестко =)

:D :D

Я не то что прикинул, я на своем довольно шустром Galaxy Note 2 заметил торможение при прокрутке.

Была мысль через tag сделать, но решил что это както примитивно и есть способ лучше.

Но видимо через tag пока само лучше.

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

 

 

Ох, обалдеть =))) Вы прикинули сколько машинного времени на это уходит ? =))) ... Но то, что Вы написали - жестко =)

:D :D

Я не то что прикинул, я на своем довольно шустром Galaxy Note 2 заметил торможение при прокрутке.

Была мысль через tag сделать, но решил что это както примитивно и есть способ лучше.

Но видимо через tag пока само лучше.

 

Вы гений рациональности и оптимизации :);)

 

P.S. не смотрел исходники TListBox'a, но, как мне кажется, ItemByIndex использует цикл. Но предполагаю, что все равно будет в много много раз быстрее, чем то, что изложено в первых рядах :)

Ссылка на комментарий
Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...