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

Belov.V.

Пользователи
  • Постов

    69
  • Зарегистрирован

  • Посещение

  • Победитель дней

    6

Весь контент Belov.V.

  1. в XE8 все запускается под iOSSimulator, все работает, но через некоторое время начинается точно также - приложение деплоится, запускается и тут же закрывается! причем, если создать новый пустой проект, то все хорошо! но через некоторое время картина повторяется! что может быть? А какая ошибка в логах симулятора? Что изменяется "через некоторое время"?
  2. Впечатляет. Обидно, что много багов. По себе знаю, как это выбивает из процесса и сколько "съедает" времени. Напишу только про BeginUpdate/EndUpdate. Не буду утверждать, что это верный подход, но в процессе экспериментов сложилось следующие мнение и подход к этому вопросу. BeginUpdate ускоряет "обновление" элементов, за счет того, что отключает срабатывание у объектов процедур, подвешенных на события on... Т.е. к примеру если не нужно, чтобы сработала обработка на events onCange, или если не важно, я включают BeginUpdate. И наоборот...
  3. чем проще? Я за себя говорю. Давайте не будем углубляться в этот вопрос. Тема про ошибку, которая существует. Если можете подсказать, как побороть ошибочное двойное выделение двух итемов при включенном sorted буду необычайно благодарен.
  4. Соглашусь с тем, что он действительно очень глючный. И без поиска, достаточно Sorted. Но иногда с ним проще.
  5. Готового решения на просторах интернета не нашел. То, что напридумывал сам, оформил в виде хелпера к TListBox. Может кому пригодится. Реализовал только необходимые мне методы. И только для режима MultiSelectStyle=None Самое главное, что так индекс возвращается корректно. unit ListBoxHelper; interface uses FMX.Controls, FMX.Types, System.SysUtils, FMX.ListBox, FMX.SearchBox; // Создаем Helper для класса TListBox type TListBoxHelper = class helper for TListBox function ResetFilter : string; // возвращает старый фильтр function GetSearchBox : TSearchBox; // возвращает SearchBox function AddAndClearSelect(const S : string) : integer; // добавить, ничего не выбирать, фильтр очистить function AddAndSelect(const S : string) : integer; // добавить, выбрать, фильтр очистить function AddAndSaveOldSelect(const S : string) : integer; // добавить, сохранить выбор, фильтр очистить function AddAndSaveOldView(const S : string) : integer; // добавить, сохранить выбор и фильтр, вернуть номер добавленного в отфильтрованном списке, или -1 если не попадает в фильтр procedure DeleteItem(const i : integer = -1); // удалить по индексу. если индекс не указан то удалить выбранный end; implementation function TListBoxHelper.GetSearchBox : TSearchBox; var Child : TControl; FxmChild : TFmxObject; begin Result := nil; for Child in self.Controls do for FxmChild in Child.Controls do if FxmChild is TSearchBox then Exit( TSearchBox( FxmChild ) ); end; function TListBoxHelper.ResetFilter : string; var s : TListBoxItem; sb : TSearchBox; begin Result := EmptyStr; s := Selected; sb := GetSearchBox; if Assigned( sb ) then begin Result := sb.Text; sb.Text := EmptyStr; end; if Assigned( FilterPredicate ) then FilterPredicate := nil; if Assigned( s ) then ItemIndex := s.Index; end; function TListBoxHelper.AddAndClearSelect(const S : string) : integer; begin ClearSelection; ResetFilter; Result := Items.Add( s ); end; function TListBoxHelper.AddAndSelect(const S : string) : integer; begin Result := AddAndClearSelect( s ); if Result <> -1 then ItemIndex := Result; end; function TListBoxHelper.AddAndSaveOldSelect(const S : string) : integer; var sel : TListBoxItem; begin sel := Selected; Result := AddAndClearSelect( s ); if Assigned( sel ) then ItemIndex := sel.Index end; function TListBoxHelper.AddAndSaveOldView(const S : string) : integer; var sb : TSearchBox; iSel, iNew : TListBoxItem; flt : string; begin iSel := Selected; iNew := nil; ClearSelection; sb := GetSearchBox; flt := ResetFilter; // Result := Items.Add( s ); if Result <> -1 then iNew := ItemByIndex( Result ); // if flt <> EmptyStr then begin sb.Text := flt; if Assigned( iNew ) then Result := iNew.Index; end; if Assigned( iSel ) then ItemIndex := iSel.Index; end; procedure TListBoxHelper.DeleteItem(const i : integer = -1); var sb : TSearchBox; flt : string; iSel, iDel : TListBoxItem; begin if i > Count-1 then Exit; sb := GetSearchBox; if i > -1 then begin iSel := Selected; iDel := ItemByIndex( i ); end else begin iSel := nil; iDel := Selected; end; flt := ResetFilter; if Assigned( iDel ) then Items.Delete( iDel.Index ); // if flt <> EmptyStr then sb.Text := flt; if Assigned( iSel ) then ItemIndex := iSel.Index; end; end. Еще на XE7 есть глюк в режиме Sorted := True, при добавить одинаковые значения (или несколько одинаковых) и сразу выделении одного через IntemIndex. Но пока на выявление закономерностей и борьбу нет времени. ListBoxHelper.zip
  6. Почитайте про "намерения" в андроиде. Явные, неявные. Думаю вопрос сам снимется, и поймете почему он немного.... в общем это не windows :-)
  7. Попробуйте в файле манифеста прописать (изменить на) android:launchMode="standatd" (скорее всего "singleTask" прописано)
  8. Тоже такое наблюдал. Датамодуль грузился первым.
  9. Можно ли в run-time определить какой SearchBox (если есть), связан с ListBox ?
  10. MainActivity()->finish() или SharedActivity()->finish() должны выгружать приложение полностью (MainActivity.finish; - корневая активити, а SharedActivity.finish - ... пока к сожалению тоже только корневая). То, что Вы видите приложение в списке не значит, что оно загружено. Это список загруженных ранее, а не находящихся в памяти. К примеру, чтобы в списке не оставался, есть ключ для файла манифеста android:noHistory="false".
  11. Вообще, дружеский совет :-) Почитайте про базы данных. В частности про язык SQL. Если в дальнейшем планируете писать программы с использованием баз данных, в том числе и легких типа SQLite, узнаете много полезного. Про составные запросы и вьюхи. Правильно спроектированная структура таблиц, индексов, констрейнов и т.д. позволяет базе данных жить "своей правильной жизнью". На тот же SQLite можно переложить часть заботы по поддержке целостности логической структуры. И код в итоге упрощается. Удачи!
  12. Способ рабочий. Часто применимый. Вы не назначаете значение Tag, поэтому и считываете 0. Картинку с кодом и результатом прикладываю
  13. Item.Tag := DataSet.FieldByName('kateg').Value; там на форме ListBox. Обращение немного другое. Сейчас картинку выложу
  14. Ну вот не удержался, извините. Если бы Вы воспользовались советом 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; Красивый код постепенно из мелочей складывается
  15. В первом сообщении писал, что если 'новые формы ''newForm.Show" или newForm.ShowModal"...' Тогда да, только в обработчике нажатия клавиши анализировать состояние форм. Но по моему мнению (не для спора), Form1.Visible:=false; Form2.Visible:=true; не лучший стиль программирования. Для андроида в плане экономии ресурсов есть смысл создавать/убивать формы динамически. А если у Вас всего лишь панели интерфейса пользователя, и которые активно используются, то есть другие способы их отображения. Но все равно потребуется писать обработчик. Если без, то смотрите решение выше...
  16. Точно? Может у Вас все же форма одна? Я даже поэкспериментировал на 3.2 и 4.4. Извините, пока железки с 5-м нет :-)
  17. Если на Андроиде в приложении Вы создаете новые формы ''newForm.Show" или newForm.ShowModal(procedure( ...., то кнопка "Назад" по умолчанию перемещает обратно между формами. Может быть имелось ввиду создание обработчика более сложного поведения внутри формы? В таком случае, при нажатии кнопки "Назад" (а так же "Menu") на форме срабатывает событие onKeyUp.Там-то и можно организовать обработку поведения: procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); begin ... // Обработка аппаратной клавиши "Back" if Key = vkHardwareBack then begin //ваш обработчик поведения .... Key := 0; // отмена стандартного действия
  18. Недавно в одном из проектов сделал так: Создал Data module На него перенес все компаненты FD* Созданный модуль прописал в uses нужных форм. Стало возможно обращаться к отобранным данным из одной формы в другой. В ListBox rowid и доп.информацию хранил в LisBox.Item(i).Tag и ListBox.Item(i).TagString (как в примере выше) Т.е. в вашем случае (к примеру юниту data module дали имя DM) в форме Form1 обращаемся к первому селекту DM.FDQuery1. При клике по строке из Listbox1 отбираем данные в DM.FDQuery2 (параметры отбора через listbox.selected... или как в примере выше). Дальше открываем Form2, где уже работаем с подготовленным набором DM.FDQuery2. Ну это если правильно понял суть Вашего вопроса.
  19. Извиняюсь за оффтоп, но хорошо бы темы закрывать верным ответом. Было бы ваше решение, возможно я сберег время :-(
  20. Как получить Intent, по которому приложение стало активным, после того, как до этого было свернутым? Как известно это метод onNewIntent(), который FMX не поддерживает. Приложение запускается в режиме android:launchMode="singleTask". Пожалуйста, не предлагайте решить задачу через ключи файла манифеста android:launchMode="singleTop" или android:launchMode="standard", которые устанавливают новый intent корневым. Там отдельные вопросы вне текущей темы.
  21. О, примерно тоже самое делал и вопрос задавал: http://fire-monkey.ru/topic/1112-android-obrabotka-prilozheniem-neiavnogo-namereniia-intent/
  22. [AlexG], и все же я не просто так предложил, т.к. поведение приложения под Android очень сильно зависит от многих факторов, к примеру от того же файла манифеста (не утверждаю, что у Вас так). Я третью неделю бьюсь с задачей корректного (по моему) поведения приложения и отсутствия зависаний при переключении между разными activity одного приложения. Так даже без изменения кода можно добиваться совершенно разного поведения программы. Кстати, так как FMX всегда возвращает ссылку на корневую активити. Пришла мысль завершать приложение с помощью: SharedActivity.finish; Описания такого способа мне не попадалось. Но ради эксперимента подвесил на одно "тяжелое" приложений и те, с которыми играюсь сейчас. Пока вроде все корректно. Интересно у кого как, в особенности у кого были проблемы.
  23. Собирите пример и выложите с описанием, как получить ошибку. Тогда посмотреть можно будет. А так гадание.
  24. Регистрируем намерение через файл манифеста (ниже для файлов с типом xml). Для Android 3.2 адекватнее работал второй фильтр: <activity … <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file" /> <data android:mimeType="text/xml" /> <data android:mimeType="application/xhtml+xml" /> </intent-filter> <!-- Для 3.2 --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file" /> <data android:mimeType="*/*" /> <data android:host="*" /> <data android:pathPattern=".*\\.xml" /> <data android:pathPattern=".*\\..*\\.xml" /> <data android:pathPattern=".*\\..*\\..*\\.xml" /> <data android:pathPattern=".*\\..*\\..*\\..*\\.xml" /> <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.xml" /> </intent-filter> Регистрируем свой обработчик события для на событие смены состояния приложения: procedure TForm1.FormCreate(Sender: TObject); var ApplicationService: IFMXApplicationEventService; begin if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, ApplicationService) then ApplicationService.SetApplicationEventHandler(ApplicationEventChanged); end; Оформляем обработчик. Получение файла можно перенести в Form1.onCreate, но я для экспериментов с activity делал тут: function TForm1.ApplicationEventChanged(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; var intent : JIntent; fileFullPath : String; begin intent := SharedActivity.getIntent; // BecameActive if AAppEvent = TApplicationEvent.BecameActive then begin if Assigned(intent) and TJIntent.JavaClass.ACTION_VIEW.equals(intent.getAction) then begin fileFullPath := JStringToString(intent.getData.getPath); if FileExists(fileFullPath) then begin // обработка файла fileFullPath // ... end; end; end // завершаем Activity при переводе приложения в "Background" else if AAppEvent = TApplicationEvent.EnteredBackground then SharedActivity.finish; // Result := True; end; Хочу обратить внимание, что привел только сам принцип. Очень важно корректно завершить активность (при сворачивании приложения, отключении экрана и т.д. ), т.к. при повторном вызове активности будет вызываться последний из стека. И если его не закрывать будем получить предыдущий, не закрытый activity. А если за приложением зарегистрировано несколько Activity (приложение можно вызвать из ланчера или как в примере, для обработки файла по типу).... в общем тут есть с чем поиграться. Для желающих посмотреть поведение и последовательность выкладываю пример, который формирует лог обработки. Нужно закоментировать: else if AAppEvent = TApplicationEvent.EnteredBackground then SharedActivity.finish; И посмотреть что и когда приложение получает в SharedActivity и AAppEvent. Ссылка в тему: http://developer.android.com/guide/topics/manifest/activity-element.html# Что не получилось: 1) Некоторые программы отдают файл в схеме «content» (к примеру Gmail v5.1 отдает). Как в этом случае получить содержание файла не разобрался. Поэтому в фильтре ограничил вид контента "file" 2) Не смог добраться до стека Activity. Если приложение в памяти и повторно вызывается с новой activity - возможно вот тут это могло пригодиться. (activity ... android:launchMode="singleTop" в этом случае не помог). ADD: было обсуждение, кто как закрывает приложения на андроид, чтобы не оставалось в памяти. Если добавлять SharedActivity.finish приложение 100% убирается из памяти. Intent_Get-File.zip
  25. С того момента, как "стал рассматривать" TGrid непосредственно как компонент отображения существующих данных, работать с ним стало проще и приятнее. В похожих ситуация работаю непосредственно с данными (выборкой). То, что FDQuery и Grid связаны через LiveBinding, значения не имеет: FDQuery1.RecNo := Grid1.Selected+1; ... := FDQuery1.FieldByName['id'].AsInteger; //или по порядковому номеру: ... := FDQuery1.Fields.Fields[0].AsInteger; //или тип Variant: ... := FDQuery1['id'] //и т.д. В зависимости от необходимого способа реакции код можно подвесить на onClick, onMouseMove и т.д. по желанию.
×
×
  • Создать...