Как динамически установить картинку из хранилища на кнопку управляемой формы в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки интерфейсов в среде 1С:Предприятие часто возникает задача кастомизации элементов управления. Например, при создании рабочего места кассира, официанта или менеджера по продажам (в стиле систем наподобие R-Keeper) требуется выводить индивидуальные изображения номенклатуры непосредственно на кнопки выбора товаров. Это делает интерфейс интуитивно понятным и ускоряет работу пользователей.

Однако при попытке реализовать это стандартными методами многие разработчики сталкиваются с трудностями и приходят к ошибочному выводу, что динамически назначить произвольную картинку кнопке или команде управляемой формы невозможно, и платформа позволяет использовать только статические изображения из встроенной библиотеки картинок метаданных. Давайте подробно разберем эту проблему, опровергнем популярные мифы и рассмотрим работающие программные механизмы для решения этой задачи.

Анализ проблемы: в чем ошибаются разработчики?

Проанализируем типичную ошибку программистов при попытке динамического изменения картинки на кнопке. Обычно код выглядит следующим образом: разработчик получает навигационную ссылку или адрес во временном хранилище для файла картинки номенклатуры и пытается напрямую присвоить это значение свойству элемента формы:


// Ошибочный код, вызывающий ошибку "Несоответствие типов"
АдресКартинки = ПолучитьНавигационнуюСсылку(Номенклатура.ФайлКартинки, "Данные");
Элементы.КнопкаНоменклатуры.Картинка = АдресКартинки;

Этот подход всегда приводит к завершению работы процедуры с ошибкой времени выполнения. Выясним причину этой ошибки. Свойство кнопки или команды Картинка ожидает на вход готовый объект типа Картинка, в то время как разработчик пытается передать туда переменную типа Строка, содержащую адрес во временном хранилище. Для исправления этой ситуации нам нужно предварительно сконструировать сам объект картинки из имеющихся бинарных данных.

Ниже мы рассмотрим три надежных метода динамического размещения изображений на элементах управления управляемой формы.

Способ №1: Прямое динамическое назначение картинки кнопке на сервере

Для того чтобы честно и без обходных путей установить картинку из базы данных или временного хранилища на кнопку, нам необходимо выполнить преобразование двоичных данных в объект Картинка в серверном контексте. Рассмотрим по шагам, как это реализовать.

Пусть у нас в справочнике Номенклатура есть реквизит ФайлКартинки, имеющий тип ХранилищеЗначения (или ссылка на справочник присоединенных файлов, откуда мы можем извлечь двоичные данные).

Напишем процедуру, которая будет выполняться на сервере и динамически изменять картинку у кнопки Элементы.КнопкаТовара (или у соответствующей команды формы Команды.ВыбратьТовар):


&НаСервере
Процедура УстановитьИзображениеНаКнопкуНаСервере(СсылкаНаНоменклатуру)
    
    // 1. Получаем двоичные данные картинки из ХранилищаЗначения
    ДвоичныеДанныеКартинки = СсылкаНаНоменклатуру.ФайлКартинки.Получить();
    
    Если ДвоичныеДанныеКартинки <> Неопределено Тогда
        
        Попытка
            // 2. Создаем объект "Картинка" на основе полученных двоичных данных
            НовоеИзображение = Новый Картинка(ДвоичныеДанныеКартинки);
            
            // 3. Назначаем созданный объект свойству Картинка нашей команды
            // Рекомендуется назначать картинку именно команде, связанной с кнопкой
            Команды.ВыбратьТовар.Картинка = НовоеИзображение;
            
            // Также можно назначить картинку напрямую элементу формы (кнопке)
            Элементы.КнопкаТовара.Картинка = НовоеИзображение;
            
        Исключение
            // Обработка исключения, если переданные данные не являются корректным изображением
            ЗаписьЖурналаРегистрации("ОформлениеКнопки", УровеньЖурналаРегистрации.Предупреждение,,, 
                "Не удалось создать объект Картинка из данных номенклатуры: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЕсли;
    
КонецПроцедуры

Этот способ является наиболее чистым и правильным с точки зрения архитектуры платформы. Он работает в рамках штатных механизмов управляемого приложения и не требует создания дополнительных элементов на форме.

Способ №2: Кликабельное «Поле картинки» (Гибкий альтернативный метод)

Если по какой-то причине прямое назначение картинки кнопке неудобно (например, при частой динамической смене картинок на клиенте без лишних серверных вызовов для перерисовки всей формы), мы можем применить популярный прием с использованием элемента формы Поле картинки, работающего в режиме гиперссылки. Этот метод отлично зарекомендовал себя в веб-клиенте и на мобильной платформе 1С.

Разберем данный подход по шагам:

  1. Создадим реквизит управляемой формы с именем АдресИзображенияТовара и типом данных Строка.
  2. Перетащим этот реквизит на форму. Автоматически создастся элемент формы.
  3. Изменим его вид на Поле картинки в свойствах элемента формы.
  4. В палитре свойств созданного поля установим флаг Гиперссылка в значение Истина. Это заставит поле реагировать на клики мыши как обычная кнопка, а курсор при наведении будет принимать форму "указательного пальца".
  5. Для этого поля определим клиентское событие Нажатие.

Теперь посмотрим на программную реализацию логики этого метода:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Получаем двоичные данные файла (например, из макета, присоединенного файла или реквизита)
    ДвоичныеДанныеИзображения = Объект.СсылкаНаНоменклатуру.ФайлКартинки.Получить();
    
    Если ДвоичныеДанныеИзображения <> Неопределено Тогда
        // Создаем объект Картинка и помещаем его во Временное Хранилище
        ОбъектКартинка = Новый Картинка(ДвоичныеДанныеИзображения);
        
        // Присваиваем реквизиту формы адрес во временном хранилище
        // Платформа автоматически считает изображение по этому адресу и отобразит его в поле
        АдресИзображенияТовара = ПоместитьВоВременноеХранилище(ОбъектКартинка, УникальныйИдентификатор);
    КонецЕсли;
    
КонецПроцедуры

&НаКлиенте
Процедура АдресИзображенияТовараНажатие(Элемент, СтандартнаяОбработка)
    
    // Отменяем стандартное поведение открытия картинки для просмотра
    СтандартнаяОбработка = Ложь;
    
    // Реализуем логику нажатия "кнопки"
    ПоказатьПредупреждение(, "Вы нажали на картинку товара! Выполняется действие команды...");
    
КонецПроцедуры

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

Способ №3: Использование современных возможностей интерфейса "Такси" (Платформы 8.3 и 8.5)

Современные версии платформы 1С:Предприятие предоставляют расширенные возможности для создания красивых графических интерфейсов. Проанализируем несколько мощных инструментов, которые могут быть полезны при проектировании плиточных меню (например, для фронт-офиса ресторана или магазина):


&НаСервере
Процедура СгенерироватьМенюТоваров()
    
    ВыборкаТоваров = Справочники.Номенклатура.Выбрать();
    Индекс = 0;
    
    Пока ВыборкаТоваров.Следующий() Цикл
        
        // Проверяем наличие картинки у товара
        Если ВыборкаТоваров.ФайлКартинки.Пустая() Тогда
            Продолжить;
        КонецЕсли;
        
        Индекс = Индекс + 1;
        ИмяКоманды = "КомандаТовара_" + Индекс;
        ИмяКнопки = "КнопкаТовара_" + Индекс;
        
        // 1. Создаем команду формы
        НоваяКоманда = Команды.Добавить(ИмяКоманды);
        НоваяКоманда.Заголовок = ВыборкаТоваров.Наименование;
        НоваяКоманда.Действие = "ОбработчикНажатияДинамическойКнопки";
        
        // Получаем изображение и преобразуем его
        ДвоичныеДанные = ВыборкаТоваров.ФайлКартинки.Получить();
        Если ДвоичныеДанные <> Неопределено Тогда
            НоваяКоманда.Картинка = Новый Картинка(ДвоичныеДанные);
        КонецЕсли;
        
        // 2. Создаем кнопку на форме и связываем ее с командой
        НовыйЭлемент = Элементы.Добавить(ИмяКнопки, Тип("КнопкаФормы"), Элементы.ГруппаПлиткаТоваров);
        НовыйЭлемент.ИмяКоманды = ИмяКоманды;
        НовыйЭлемент.Отображение = ОтображениеКнопки.КартинкаИТекст;
        
    КонецЦикла;
    
КонецПроцедуры

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

Резюме и рекомендации

Мы детально изучили проблему динамического назначения изображений на кнопки управляемых форм и убедились, что утверждения о невозможности такой реализации — не более чем миф. Чтобы успешно применять графические элементы на формах 1С, придерживайтесь следующих правил:

  1. Всегда преобразуйте двоичные данные файлов изображений в объект типа Картинка перед тем, как присвоить их свойствам кнопки или команды на сервере.
  2. Для простых сценариев используйте прямое назначение картинки свойствам Команда.Картинка или Элемент.Картинка.
  3. Если разрабатывается сложная форма с большим количеством графических элементов или форма ориентирована на работу в веб-клиенте / мобильном приложении, отдавайте предпочтение элементам Поле картинки в режиме Гиперссылка, связывая их с адресами во временном хранилище.
  4. Используйте возможности современных версий платформы 1С v8.3 и v8.5, такие как кнопки-карточки и программное создание интерфейсов, для получения наилучшего визуального результата и высокой скорости работы приложения.
← На главную