Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Датасет и компоненты на форме


Автор: Dapo 30.6.2010, 03:36
Доброе время всем! Прошу совета по алгоритму, а точнее по организации связей полученного датасет-а и компонентов на форме. Датасет возвращается скл-запросом в виде таблицы где значения элементов расположены в столбик. Поля такие: ID_tag, Name, Value, Date_Time. Необходимо привязать эти значения к компонентам на форме (например к TLabel). Пока кроме как такого ничего не придумал: в цикле бежать по компонентам, находить TLabel, в датасет-е делать локэйт по полю ID_tag по значению из TLabel.Tag и заполнять TLabel.Caption значением Value. Дело усугубляется тем, что операцию эту нужно проводить в потоке (по понятным причинам) а TLabel-ов может быть довольно много ~2000 (предполагается наличие вкладок-мнемосхем) и Synchronize так же будет вешать прогу как если-бы операция выполнялась в основном потоке (может не прав?). Есть здоровое мнение - обновлять только видимые компоненты, для чего нужно будет создать для каждого визуального компонента свой record (т.к. обрабатывать необходимо все значения полученные в датасет-е). Есть ли у кого идеи на этот счет или двигаться в том направлении которое описал?

Спасибо.

Автор: Alexeis 30.6.2010, 08:59
  На всякий случай, а вы в курсе про компоненты типа TDBText, TDBEdit? 

Автор: Dapo 30.6.2010, 09:45
Alexeis, в курсе. зато не в курсе каким образом конкретный TDBEdit привязать к конкретному кортежу в датасете, а вы в курсе?

Автор: Akella 30.6.2010, 12:56
Там есть свойства DataSource и DataField (FieldName)

Автор: Alexeis 30.6.2010, 13:11
Dapo, на самом деле датасет выдает данные по строкам, поэтому привязаться к 2м строкам одновременно можно только 2мя запросами.
  Похоже на нестандартное использование БД. Быть может, вы строите отчет? Опишите более обще задачу, возможно для нее есть другое стандартное решение.

Автор: Dapo 1.7.2010, 02:25
Akella, (+1)  smile 

Alexeis, о чем и речь. Я ведь сразу указал - где значения элементов расположены в столбик. Поля.... И вроде даже алгоритм описал... видимо не внятно. Ну ладно, вроде сейчас все ясно.

Смысл задачи в следующем: данные в таблице - значения сигналов неких датчиков (тэги). Таблица имеет поля (см. сабж). скл-запрос выдергивает последние значения тэгов и передает датасет с такими же полями клиенту. По данным полученого датасета нужно заполнить мнемосхему состояния техпроцесса. "Заполнить" - значит отрисовать значения на элементах мнемосхемы (для простоты TLabel, вообще будет свой компонент связка tpanel+tlabel+tedit). Оператор не будет видеть все 2000 тэгов, а будет видеть только одну логическую группу, но тем не менее все значения датасета должны пройти обработку на предмет выхода значения из допуска и соответсвенно просигнализировать об этом оператору, чтобы он мог переключиться на "проблемную" логгруппу. Должен сказать, что запросом будет возвращаться фиксированное количество тэгов. Вот в наиболее эффективной реализации сказанного я и ищу совета. Предложенный мной алгоритм не нравиться тем, что придется использовать цикл по компанентам + локэйт по датасету+Synchronize для каждого компонента так как запросы будут обрабатываться в отдельном потоке.

Автор: Alexeis 1.7.2010, 09:46
  Как вариант, выводить в DBGrid. На счет производительности могу подкинуть такую идею. Отказаться совсем от TLabel и просто выводить текст на канвасе. В потоке сделать Canvas.Lock() .... Canvas.UnLock() . После блокировки канваса на нем можно рисовать из другого потока.

Автор: Dapo 2.7.2010, 02:33
Alexeis, издеваетесь, да? Мнемосхема в виде DBGrid-а? Я бы уволил за такое решение  smile кагбэ не задумываясь. Выводить в канвас - вариант неплохой с точки зрения синхронизации, но с точки зрения "сборки" мнемосхемы через канвас... аж дрожжж берет  smile . Мнемосхема - это такая штука с картинками, анимашками, метками и полями ввода, которые имеют свойство видоизменяться в зависимости от события. Почти со всеми элементами возможно взаимодействие пользователя (как минимум события мышки). Ну с какой тут стороны канвас прикрутить? Хотя по синхронизации очень заманчиво. Было такое мнение - формировать таблицу с поинтерами, и ID_tag на стороне клиента, передавать ее сереверу и джоинить с таблицей значений тэгов по ID_tag. Возвращать результат клиенту и дальше опять в цикле бежать уже по датасету и напрямую через поинтер обновлять значение на мнемосхеме. Становиться страшно за сервере (5-6 клиентов одновременно, каждую секунду временная таблица) хотя... может зря боимся?

Может вообще что-то радикальное? Только вот что?

Автор: Alexeis 2.7.2010, 09:22
Цитата(Dapo @  2.7.2010,  01:33 Найти цитируемый пост)
Я бы уволил за такое решение

  Мало ли smile . 
Цитата(Dapo @  2.7.2010,  01:33 Найти цитируемый пост)
Мнемосхема - это такая штука с картинками, анимашками, метками и полями ввода, которые имеют свойство видоизменяться в зависимости от события. Почти со всеми элементами возможно взаимодействие пользователя (как минимум события мышки). Ну с какой тут стороны канвас прикрутить? 

  Канвас можно к чему хош прикрутить, точнее к любому оконному компоненту. Необязательно же всю отрисовку делать в том же потоке. Мнемосхемы можно запускать в основном потоке. Для этого и используется Lock. Пока рисуются надписи не рисуются мнемосхемы и наоборот. События инициировать можно без Synhronize. Из главного потока удобно использовать эвенты. В этом случае поток мгновенно пробуждается и выполняет работу. Главному потоку можно сигнализировать по помощи пересылки сообщений (SendMessge), поскольку основное время приложение находиться в ожидании этих самых сообщений, то синхронизация будет быстрой.

Автор: Dapo 5.7.2010, 01:39
Alexeis, ну почти убедили smile А теперь, если не сложно, коротко, словами опишите светлый путь от получения датасета до отрисовки значения на мнемосхеме? А то что-то у меня картинка не складывается.  smile Как работать с канвасом знаю. Спасибо.

Автор: Alexeis 5.7.2010, 10:21
Цитата(Dapo @  5.7.2010,  00:39 Найти цитируемый пост)
словами опишите светлый путь от получения датасета до отрисовки значения на мнемосхеме? 

  Ээ.. мне думается что с БД я знаком меньше вашего  smile . Полагаю что не нужно рассказывать как использовать методы First() / Next() и проверять на Eof() . Т.е. перечисляем строки и с заданным интервалом (зависит от высоты шрифта), выводим на битмап такого же размера как окно (если нет нативной двойной буферизации). По окончанию делаем Canvas.Draw битмапу. Кстати пришла в голову еще такая идея. Синхронизировать только отрисовку битмапа на канве. На битмапе то можно из любого потока рисовать. Нарисовали на битмапе, после чего для указанного окна вызываем WinApi функцию InvalidateRect, она в свою очередь сообщение WM_ERASEBKG / WM_PAINT . У компонента делаем обработчик OnPaint в котором и будем рисовать битмап на канве окна. Если окно может растягиваться, то не забыть еще OnResize.

  Возникают еще вопрос влезут ли все поля. Или как их разместить. Посчитать количество видимых полей можно по формуле высота окна / (высота текста + высота промежутка). Тут нужно обратить внимание что высота шрифта может описываться отрицательной величиной (зависит шрифт + промежуток или только высота шрифта)

  Если вопрос производительности стоит остро, могу посоветовать 
1) Запросом извлекать только необходимые поля.
2) Адресовать поля по индексу, а не по имени.
3) По возможности не производить лишних конвертаций типов.




Автор: Dapo 6.7.2010, 01:44
Alexeis, спсаибо, из за чего в дрож и бросало  smile  (именно заморочки с определением координат, высот, расстояний), если например через пару месяцев возникнет необходимость реорганизовать мнемосхему - добавить/удалить тэг или просто переместить. В идеале хотелось бы конструктор мнемосхем сделать, ну да ладно, видимо все-таки придется ваять методом проб и ошибок. А все три ваших совета свято соблюдаю  smile Всем удачи!

Автор: Alexeis 6.7.2010, 09:04
Цитата(Dapo @  6.7.2010,  00:44 Найти цитируемый пост)
Alexeis, спсаибо, из за чего в дрож и бросало  smile  (именно заморочки с определением координат, высот, расстояний), если например через пару месяцев возникнет необходимость реорганизовать мнемосхему - добавить/удалить тэг или просто переместить

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)