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

RoschinSpb

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

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

  • Посещение

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

    10

Весь контент RoschinSpb

  1. Не ссоритесь девочки пож. Возвращаясь к сути вопроса. Основная сложность тут в том, что в Delphi нельзя разрушать экземпляр класса внутри метода этого класса за исключением тех случаев, когда метод использует только для разрушения Free, DisposeOf. Почему так, а не иначе, какие есть исключения и почему "уменяфсёработает" объяснять долго, поэтому в первом приближении предлагаю принять это за аксиому. Обработчики событий OnClick и пр. вызываются из методов классов, так что разрушать контрол внутри события нельзя от слова совсем. Кроме очевидных случаев типа Self.DisposeOf существуют более запутанные варианты, когда к примеру закрывает и разрушается форма, что приводит к разрушению всех дочерних контролов. Образно говоря, самоубийства строго запрещены, но не запрещено нанимать киллера и в качестве жертвы указывать себя. Т.е. должен быть некий другой (глобальный) объект который будет разрушать объекты, которые хотели бы самоубицо. Реализацию такого объекта можете придумать сами, или использовать TPurgatory (чистилище, в католическом учении — промежуточное место между раем и адом). Но чтобы убедиться в правильности работы можно создать своего наследника TButton в котором перекрыть деструктор и поставить в нем точку останова. При запуске в режиме отладки посмотрите стек вызова деструктора (надо быть внимательным, он может быть длиннющим), ни где в этом стеке не должно быть метода разрушаемого экземпляра. Если в Вы нашли метод разрушаемого объекта (за исключением вышеуказанных), то Ваш способ удаления работает не правильно и с некоторой долей вероятности будет приводить к AV и другим "неприятностям" которые почти невозможно отловить в режиме отладки.
  2. Зря Вы TPurgatory угробили Простой пример: при потере фокуса закрывается всплывающее меню и разрушается всплывающая форма с этим меню, на OnClick всплывающего меню повешен обработчик, в обработчике возникает исключение которое приводит к появлению окошка с сообщением об ошибке появление окна с сообщением об ошибке закрывает и разрушает контекстное меню получается внутри метода объекта мы совершенно незаметно для себя уничтожили этот объект и на выходе из обработчика OnClick мы уже попадаем ... куда? В код разрушенного объекта. Может там остались старые данные и всё отработает нормально, а может там уже данные другого объекта, или еще какой мусор и приложение аварийно выкидывается из памяти. Как оно в итоге получится зависит от везения и фазы луны. Подобные ситуации могут возникнуть и в других, менее очевидных случаях. Так что будьте бдительны.
  3. Используйте сразу Berlin, там есть пример как использовать DB Grid c набором данных. XE3 + Fire Monkey -> даже не мучайтесь, во-первых мало что получится, во-вторых всё равно надо буде переделывать при переходе на следующие версии.
  4. Вообще много что поменялось в TGrid при переходе от 10.0 к 10.1. Процедура удалена за ненадобностью. Что конкретно Вы хотите чтобы было сделано? Для начала посмотрите, будет ли работать без неё.
  5. Теоретически возможно всё. Практически, если бы это было возможно сделать без переписывания FMX, то это бы сделали с самого начала.
  6. Как я понимаю здесь не применим и GetSystemMetrics(SM_TABLETPC)<>0, т.к. в общем случае можно курсор двигать и с помощью мыши и с помощью пальца. Существуют обычные настольные мониторы с сенсорной поверхностью. Тут наверно нужно учесть, что пользователь обычно не водит пальцем по сенсорному экрану, а просто тыкает пальцем на контролы, исходя их этого допущения можно что-то придумать с подсказками. Мой совет: лучше исхитряться в сторону использования стандартных высокоуровневых возможностей остаётся в силе
  7. Если всё прикладное приложение обвешивать директивами условной компиляции, то реально работать будет невозможно, не говоря уже о том, что в этом случае надо будет изучить апи каждой платформы. Поэтому лучше исхитряться в сторону использования стандартных высокоуровневых возможностей. Директивы условной компиляции обычно используются только для тех случаев, где действительно логика работы зависит от платформы: {$IFDEF MSWINDOWS} Caption := Caption + ' for Windows'; {$ENDIF} В данном случае проверять наличие значения Touch в Shift.
  8. Подозреваю Shift содержал значение ssTouch GetSystemMetrics(SM_TABLETPC)<>0 На андроиде работает? Это я к тому, что если Вы привязываете работу только к Windows, то лучше пользоваться VCL это и проще и стабильнее и сторонних библиотек немеряно написано. А при использовании FMX не стоит использовать системные функции т.к. это уничтожит одно единственное достоинство Fire Monkey - кроссплатформенность.
  9. Можно попробовать TListBox.AniCalculations.MouseWheel См. также Платформонезависимый скроллинг в Fire Monkey
  10. RoschinSpb

    Canvas,

    Если всё сделать в одном блоке BeginScene EndScene, и без Application.ProcessMessages и Repaint не заработает? if panel.Canvas.BeginScene then try // рисовать всё finally panel.Canvas.EndScene; end;
  11. На всякий случай, напомню, если контрол или канву повернуть, то все обрезки перестают действовать на мобильных устройствах.
  12. Да, именно так, сам на это напарывался, даже вроде баг заводил. Понять это невозможно, это надо знать! Раздел Uses может добавиться автоматически, например по Ctrl+A и он добавляется после implementation и перед %CLASSGROUP.
  13. Да. Во всяком случае так было в той версии которая у меня и которой я занимался. Задержка порядка 50 мс. это мало, чтобы заметить но не 0. Если бы задержки не было вообще, то при любой попытке скрола, менялась бы выделенная ячейка. Вот видео, записал как смог. Это ни как не настраивается, просто после многих проб и ошибок подобрался наиболее оптимальный вариант. Похожий на стандартное поведение. Да, были с этим проблемы, при чем как всегда: "Не знаю, не знаю, у меня всё работает, что у вас за телефон?". Тут надо понимать, что это некие искусственные события которые эмулируют работу с мыши т.е. добавляют свою логику поверх системной, и там в зависимости от модели могут быть разные особенности, лучше обрабатывать жесты. Посмотрите исходники, можно сделать по образу и подобию. А чем собственно не удовлетворяет стандартное поведение? Я так и не понял.
  14. Да, действительно в случае грида, перемещение пальца не рассматривается как клик по ячейке, а рассматривается как скроллирование. Если прикоснулся пальцем и держал на месте короткое время, или прикоснулся и сразу отпустил не перемещая, то это считается желанием выделить ячейку (начать редактирование), и приводит к событию OnCellClick. Если прикоснулся пальцем и сразу начал двигать, то считается что пользователь захотел переместить рабочую область таблицы (проскроллировать) и это не приводит к выделению ячейки и событию OnCellClick. Это нормальное и корректное поведение: ячейки "не кликаются", когда пользователь просто перетаскивает рабочую область таблицы. Если хотите странного, то обрабатывайте события OnMouseDown, OnTap и т.п. по своему собственному усмотрению на свой страх и риск игнорируя всю остальную логику работы таблицы.
  15. Потому, что изначально все контролы были заточены на использование стилей. Подмена стиля влечет за собой изменение всех цветов оптом. Если Вы прибиваете гвоздями некий цвет то при различных стилях это будет выглядеть непредсказуемо. Например: хотите сделать желтый грид в то время как умолчательный цвет окна белый, вроде нормально... теперь допустим оказалось, что стиль какой-нибудь темно-зеленый фон со светло-салатным текстом, получаем ядовитую таблицу с практически нечитаемым текстом. Вам это надо? Не обязательно даже использовать какой-нибудь экзотический стиль. В IOS и Android в зависимости от системных настроек может быть светлый и темный стиль, т.е. белые окна с черным текстом и черные окна с белым текстом. Кроме того как такового цвета грида не существует, т.к. в качестве фона используется картинка. При использовании стандартных стилей она представляет из себя сплошную заливку, но в некоторых стилях там присутствует некоторый фоновый рисунок. Обработчик события по которому можно самостоятельно рисовать ячейку имеется, но он не работает для случая нативного грида по причине тормозов с отрисовкой. Вообще рисование на канве мобильных устройств выполняется очень медленно отсюда и жалобы на неадекватные тормоза гридов и прочего, что сподвигло на широкое использование родных-нативных контролов. Почему изначально всё заточено на стили, ну... так исторически сложилось, за подробностями обращайтесь к автору.
  16. Для придания завершенности Вашему контролу надо бы еще реализовать интерфейс ITextSettings чтобы можно было использовать его как в примере:
  17. Ячейка/эдит/мемо с данными, которые не могут меняться, нужны для того, чтобы хотя бы скопировать весь, или часть текста в буфер обмена, для этого и существует свойство ReadOnly. Только текст который не содержит меняющихся данных (метка/заголовк) практически ни когда не требуется копировать в буфер обмена, но такие элементы пользовательского интерфейса не требуют и получения фокуса ввода. Запрет на выделение ячейки легко делается OnSelectCell. Ввод новых свойств с мутным смыслом всегда дело неблагодарное. Например: Enabled := False; Editing := True; Серая колонка, нельзя войти в режим редактирования ячейки -> Баг! Я поставил Editing в True, очевидно что должна быть возможность войти в режим редактирования. Вы там с логикой дружите? Серая колонка, можно войти в режим редактирования -> Баг! Колонка выглядит как недоступная, тем не меняя можно войти в режим редактирования. Что за дизайн? Обычная колонка, нельзя войти в режим редактирования -> Баг! Enabled у меня стоит False, а колонка выглядит как доступная, очевидно что если Enabled = False, должна быть серая как и все элементы управления. Вы лучше баги правьте, а не ломайте то, что работает! Обычная колонка, нельзя войти в режим редактирования, Enabled становится False -> Баг! В очередной версии почему-то свойство Enabled самопроизвольно меняет своё значение. Почему в каждой версии что-нибудь да отваливается? TGridOption.Editing = not Grid.ReadOnly - полезно для ситуаций, когда надо явно переходить в режим изменения данных с использованием блокировок. Нажимаем кнопку "изменить" - можно вводить данные, нажимаем кнопку "применить" - нельзя вводить данные, но по прежнему можно смотреть. Было бы не плохо, если бы Вы тут выложили пример своей идеальной колонки, это бы ввело обсуждение в конструктивное русло. А то после всего написанного Капитан Очевидность шепчет о том, что к программированию Вы имеете весьма опосредованное отношение, но я конечно не верю. В конце концов хороший программист не обязан писать повести как Лев Толстой и тут простого примера было бы достаточно, чтобы расставить все точки над Ė, да и след в истории будет хороший. За сим прощаюсь, т.к. действительно общение вышло за рамки заявленной темы и превратилось в оффтоп переходящий в троллинг.
  18. Может но не обязан, так же как и Ваше идеальное событие. Так же как аналогичное VCL-ное событие работает с прошлого века, странно, что Вы этого не знаете программируя начиная с Delphi2. Т.е. свойство которое запрещает редактирование доступного столбца (любопытно, должно ли оно разрешать редактирование недоступного столбца?). Да, как-то за пять лет заявок не эту тему не припомню. У TEdit, кстати тоже есть только ReadOnly и Enabled, а что-то среднее называется TLabel и ни кто не жаловался. Конечно реальная жизнь сложна и многогранна наверняка найдется пользователи которым это понадобилось бы, кому-то и розовый котенок в пятом углу нужен, но данный функционал не особо востребован. Так или иначе есть возможность создать своего наследника колонки и в Runtime, и зарегистрировать его в IDE для работы в DesignTime.
  19. А я вот сварил: procedure TForm1.Grid1SelectCell(Sender: TObject; const ACol, ARow: Integer; var CanSelect: Boolean); begin if (ACol = 1) and (ARow = 2) then begin CanSelect := False; if Sender is TStringGrid then begin TStringGrid(Sender).Cells[2, 5] := IntToStr(TStringGrid(Sender).Col) + ' ' + IntTostr(ACol); TStringGrid(Sender).SelectCell(2, 5); end; end; end; Можно получить информацию и по старому столбцу и по новому и выделить ту ячейку, которую хочу. И чем же CanSelect это идиотизм по сравнению с Вашим идеальным var NewCol, NewRow: Integer, а вот OnClick не идиотизм в сравнении с OnCellClick? В общем это риторический вопрос. Магическая кнопка TColumn.CanEdit - виртуальный метод в дополнение к TColumn.Enabled и TColumn.ReadOnly, которые можно менять. Используется в основном для определения того, поддерживает ли колонка определенного класса редактирование значений в принципе, например TProgressColumn не поддерживает. Но если Вы реализовали двойной клик на ячейке через OnClick на гриде, то очевидно для Вас не составит труда и добавить свойство в колонку с использованием CanEdit. TGridOption.Editing - добавлен то ли для совместимости, то ли как аналог TGrid.ReadOnly когда его еще не было, есть не просит, удалять не просили. CancelEditingByDefault - была личная инициатива раньше этой опции не было и ни кто на это не жаловался, но я думаю что если Вы напишите в QC предложение распространить это свойство еще и на колонки начав своё письмо со слов Dear idiots, то безусловно в сжатые сроки предложение будет рассмотрено. Да есть, прямиком из ЦРУ..., но есть и еще более секретная директива от самого... сами знаете кого, которая всё ломает.
  20. с сильными и слабыми ссылками По этому поводу можно по-читать эпосы Allen'а Bauer'а. По мне так это "былинный отказ", но не будем о грустном.
  21. А вынести код в свой отдельный метод и его уже вызывать из обработчика события тоже религия не позволяет? Столбец ACol может быть Disabled, или просто по некоторым причинам мы не хотим попадать в ячейку, если Вам этой функциональности не нужно это не значит, что её не нужно ни кому. Если Вы для ACol указали недоступный столбец, то либо будет совершенно незаметно для вас выделен не тот столбец который вы хотели выделить, либо будет исключение в недрах реализации Grid`а. Поэтому есть два события OnSelectCell и OnSelChanged по первому определяем (если надо) хотим ли мы выделить ячейку (любым способом), а второе срабатывает когда действительно перешли в другую ячейку. Да это отдельные события которые не OnClick и не OnDblClick. OnCellDblClick - факт двойного клика/экшена по заданной ячейке (строке). OnDblClick - факт двойного клика по области, которую занимает грид, почувствуйте разницу. Это вовсе не факт того, что это приведет к смене выделенной ячейки, и даже не факт того, что под курсором находится ячейка. Это унаследованное событие, которое которое работает так же как на любом контроле (button/label/switch) менять логику работы - значит поломать существующий ранее написанный код который исходил из этой логики работы. Само по себе знание того, что куда-то в область Grid дважды кликнули имеет мало смысла, требуется точно знать куда кликнули и что с этим делать, с учетом кучи свойств Grid'a и столбцов. Т.е. требует реализацию некоторой нетривиальной логики работы повторяющей логику работы TGrid - это я и называю изобретением велосипеда. Если для вас это не проблема, то уж тем более не будет проблемой в Run-Time присвоить событие. Да, это я понял. Между двумя пальцетыками грид может уехать на несколько строк. На быстрый пальцетык не меняем выделенную ячейку, на долгий - меняем. По первому пальцетыку можем выбрать нужную ячейку, по второму войти в режим редактирования, либо по первому тычку войти в режим редактирования, а по второму вывалить выпадающий список... это только то что на вскидку спустя год вспомнилось. И тут еще и сам пользователь что-то добавляет, забыв проверить доступность ячейки.
  22. Обрабатывать OnDblClick - это и есть изобретение своего велосипеда и выполнение того, что должен выполнять сам компонент. Все просто в простейших контролах типа кнопки, когда не предусмотрено ни какой другой логики кроме выполнения события. А вот для TSwitch не всё так однозначно, там поведение уже более сложное (можно его переключить сдвинув пальцем и это не будет кликом). В Grid совсем все сложно. Логика поведения навороченная и любая отсябятина её поломает с непредсказуемыми последствиями. Клик произошёл. Так что выделена ячейка должна быть под точкой клика. А кто-то (и таких людей наберется не мало) может сказать, "по клику я хочу сам выделить ячейку ту, которую считаю нужной, а не ту на которую ткнул пользователь". Допустим в одном столбце картинка во втором значение и по клику на картинку я хочу выделить соседнюю ячейку с изменяемым параметром. Кроме того не факт, что под курсором оказалась "не задизабленая" ячейка, об этом должен не забыть подумать прикладной программист. Скроллирование тут при том, нажатие и отпускание мыши (пальца) происходит примерно в рандомном месте (два раза). На нажатие-отпускание пальца реакция может быть разной, скроллирование может остановиться/замедлится/пойти в другую сторону, при долгом нажатии остановиться и выделиться ячейка. OnCellDblClick ведь сериализировать нельзя на единый обработчик кликов. Так и да, сделать два обработчика вместо одного — воистину адская по сложности работа :o) Да и странно, что таблица реагирует на нажатие также как кнопка, хотя всякое бывает. Если продолжить философские рассуждения, то на контролах не должно было быть событий относящихся к аппаратным средствам. Потому, что на разных платформах может быть мышь, а может сенсорный экран что на первый взгляд похоже но не совсем одно и то же, а может быть и то и другое, кстати и в этом разобраться очень трудно. Должны быть события относящиеся именно к контролам, к примеру вместо OnClick на кнопкообразных контролах должно быть что-то типа OnExecute. Может кликнули мышью, может ткнули пальцем, может нажали пробел на клавиатуре, может сдвинули пальцем переключатель, может еще что угодно о чем нам знать не обязательно и за это отвечает контрол — но в итоге произошло нечто в результате чего мы должны выполнить некоторое действие. Также и в Grid можно десятью способами реагировать на разные клики/жесты в разных местах на разных платформах (включая будущие). На сколько правильно остаётся на совести компонента. Прикладной программист обрабатывает события не вдаваясь в подробности о том, в результате каких манипуляций они произошли, но реализует логику работы о которой можно догадаться из названия или краткой справки. Например OnSelectCell - неважно что произошло в подлунном мире, но грид хочет знать можно ли выделить определенную ячейку. OnSelChanged - опять, ни кого не интересует каким образом это произошло, но выделенная ячейка поменялась. OnExecute - надо выполнить какое-то действие. OnAltExecute - надо выполнить какое-то альтернативное действие и т.п. К сожалению изначально на эту тему не задумывались. Сохранили совместимость с виндовой VCL там, где этого не следовало делать. Зато поломали совместимость там где в этом не было серьезной необходимости Caption -> Text; Left, Top: Integer -> Position.X, Position.Y: Single; Font.Color -> FontColor А ведь если бы можно было VCL-ный dfm запустить на андроиде... не, это было бы конечно не так круто, как натянуть грид на грани вращающегося куба, но гораздо более востребовано на практике.
  23. Потому, что Х3 как определить то, что находится в гриде под курсором (обычная ячейка, недоступная ячейка, редактор ячейки, заголовок, пустое место), особенно в момент скроллирования на телефоне где и мыши-то нет. И ХЗ когда менять выделенную ячейку до срабатывания события, после срабатывания события, после первого клика, или после второго. И ХЗ как реагировать самому гриду на клик, если пользователь сам уже что-то сделал... Поэтому в дизайнер введены другие события например OnSelectCell, OnCellDblClick, которые срабатывают в таком порядке OnSelectCellOnSelChangedOnCellClickOnCellDblClick
×
×
  • Создать...