При разработке сложных интерфейсов, таких как автоматизированные рабочие места (АРМ) весовщиков или кассиров, программисты часто сталкиваются с необходимостью обновления данных на форме в реальном времени. Типичный сценарий: подключение весового оборудования, данные с которого должны считываться каждые 100 миллисекунд (0.1 сек). Однако здесь разработчиков подстерегает неприятный сюрприз — в строковые или числовые поля на этой же форме становится невозможно ввести данные: текст постоянно сбрасывается или поле очищается сразу после ввода. Проанализируем эту ситуацию и разберем, как обойти ограничения платформы.
Разберем по шагам, что происходит внутри платформы 1С при выполнении кода в обработчике ожидания. В управляемых формах реализовано четкое разделение между данными реквизита (хранящимися в памяти) и текстом в поле ввода (который видит пользователь). Когда оператор начинает набирать текст в поле, эти данные еще не попали в реквизит формы — они находятся во временном буфере элемента управления.
Как только срабатывает ПодключитьОбработчикОжидания и внутри процедуры происходит присвоение значения любому другому реквизиту (например, обновление веса), платформа инициирует цикл синхронизации состояния формы. Система проверяет соответствие всех отображаемых данных значениям в реквизитах. Поскольку пользователь еще не нажал Enter и не перевел фокус (событие изменения не завершено), данные в текущем поле считаются «грязными». Платформа в попытке сохранить целостность данных может принудительно обновить поле ввода значением из реквизита, которое на данный момент является пустым. В итоге — введенные символы исчезают.
Самый простой и эффективный способ исправить поведение — изменить настройки самого элемента формы. Рассмотрим подробнее свойство ОбновлениеТекстаРедактирования (UpdateTextEditing). Оно определяет, в какой момент система должна синхронизировать текст в поле с данными реквизита.
Важное замечание: Если ваша конфигурация работает в режиме совместимости с версией 8.2.13 или ниже, это свойство может не влиять на поведение. В таких случаях необходимо либо повышать режим совместимости, либо использовать альтернативные методы, которые мы разберем далее.
Если нам нужно отображать вес в реальном времени, но мы не хотим нагружать цикл обновления всей формы 1С, мы можем использовать поле HTML. Этот метод позволяет обновлять конкретный фрагмент интерфейса с помощью JavaScript, не затрагивая стандартные механизмы синхронизации реквизитов 1С. Рассмотрим пример реализации:
Сначала подготовим процедуру в модуле формы для вызова из обработчика ожидания:
&НаКлиенте
Процедура ОбработкаОжиданияЭкспорт() Экспорт
// Получаем данные с весов (в примере - генератор случайных чисел)
ГСЧ = Новый ГенераторСлучайныхЧисел;
НовыйВес = ГСЧ.СлучайноеЧисло(0, 500);
// Передаем значение напрямую в HTML-поле без обновления реквизитов формы
Элементы.ПолеВесаHTML.Документ.showWeight(НовыйВес);
// Переподключаем обработчик для однократного вызова (точность 0.1 сек)
ПодключитьОбработчикОжидания("ОбработкаОжиданияЭкспорт", 0.1, Истина);
КонецПроцедуры
Затем инициализируем HTML-разметку при открытии формы:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ТекстHTML = "
|<html>
|<body style='margin:0; padding:0; font-family: sans-serif; font-size: 24px; color: green;'>
| <div id='weightDisplay'>0</div>
| <script>
| document.showWeight = function(weight) {
| document.getElementById('weightDisplay').innerHTML = weight + ' кг';
| };
| </script>
|</body>
|</html>";
ПолеВесаHTML = ТекстHTML;
ПодключитьОбработчикОжидания("ОбработкаОжиданияЭкспорт", 0.1, Истина);
КонецПроцедуры
Этот подход полностью изолирует процесс отображения веса от процесса ввода данных в другие поля. Пользователь может спокойно печатать в строковых полях, пока JavaScript обновляет цифры на экране.
Проанализируем ситуацию: действительно ли нам нужен полноценный реквизит формы для отображения текущего веса? Если вес используется только для визуального контроля, а фиксация происходит по нажатию кнопки, то использование Поля ввода избыточно.
Заменим элемент формы на Декорацию-надпись. Изменение свойства Заголовок у декорации гораздо «легче» для графического движка 1С, чем изменение значения реквизита. Посмотрим на пример кода:
&НаКлиенте
Процедура ОбработкаОжидания() Экспорт
ТекВес = ПолучитьДанныеСДрайвера(); // Ваша функция опроса оборудования
Элементы.ДекорацияВес.Заголовок = Формат(ТекВес, "ЧЦ=15; ЧДЦ=3") + " кг";
ПодключитьОбработчикОжидания("ОбработкаОжидания", 0.1, Истина);
КонецПроцедуры
Такой метод позволяет избежать установки признака Модифицированность для всей формы при каждом тике таймера, что положительно сказывается на стабильности ввода в соседние поля.
Если данные веса необходимы для логики программы (расчетов), но не должны мешать интерфейсу, мы можем сохранять их в переменную модуля формы, а не в реквизит. Выясним причину, почему это помогает: изменение переменной, объявленной через Перем, не вызывает уведомления формы об изменении данных, а значит, и не запускает цикл перерисовки контролов.
Перем ТекущийВесВПамяти;
&НаКлиенте
Процедура ОбработкаОжидания() Экспорт
ТекущийВесВПамяти = ОпроситьВесы(); // Данные сохраняются тихо
// Обновляем визуальное поле только если оно не в фокусе или по условию
Если Элементы.ПолеВеса.Доступность Тогда
// Логика обновления
КонецЕсли;
КонецПроцедуры
Частота 0.1 секунды (100 мс) является экстремальной для однопоточного пользовательского интерфейса 1С. Выполняя код так часто, мы забиваем очередь сообщений Windows событиями перерисовки. Рассмотрим рекомендации по оптимизации:
Подводя итог, можно сказать, что проблема «исчезающего текста» — это не баг платформы в чистом виде, а особенность синхронизации данных. Используя настройку ОбновлениеТекстаРедактирования или вывод через HTML/Декорации, вы сможете создать комфортный и отзывчивый интерфейс даже при работе с высокоскоростным оборудованием.