- •Принципы создания графических интерфейсов
- •Постановка задачи
- •3. Среда guide
- •3.2. Конструирование интерфейса
- •3.3. Работа над приложением
- •3.4. Программирование элементов интерфейса
- •3.5. Диалоговые окна и меню приложения
- •Пример графического интерфейса пользователя
- •Листинг исходного кода приложения
3.4. Программирование элементов интерфейса
3.4.1. Флаги и рамки
Флаги (Checkbox) используются для изменения величин с двумя возможными значениями. Продолжите совершенствование приложения, предоставив пользователю возможность наносить линии сетки на график. Окно приложения должно содержать два флага с надписями сетка по X и сетка по Y. Когда пользователь установит один из флагов, на графике должна отобразиться соответствующая сетка.
Обычно несколько элементов управления со схожим назначением группируются и внутри рамки (Frame). Измените размеры элемента Axes, освободив, справа место для рамки. Нанесите рамку на окно приложения при помощи соответствующей кнопки. В рамку добавьте два флага. Разместите поясняющие подписи рядом с флагами и дайте им имена chbxGridX и chbxGridY. Произведите необходимые изменения кода.
Листинг 6. Обработка событий отображения сетки. mygui.m:
function chbxGridX_Callback(hObject, eventdata, handles)
set(handles.axMain, 'XGrid', mapValue(hObject, 'Value'));
function chbxGridY_Callback(hObject, eventdata, handles)
set(handles.axMain, 'YGrid', mapValue(hObject, 'Value'));
Листинг 7. Преобразование булевских значений в строковые. myValue.m:
function retval = mapValue(hObject, property)
if get(hObject, property)
retval= 'On';
else
retval='Off';
end
3.4.2. Переключатели
Переключатели (Radio Button) предоставляют пользователю возможность изменять величины с несколькими возможными значениями. Соответственно всегда установлен единственный переключатель из группы. Предоставьте пользователю возможность выбирать тип маркера (кружок, квадрат или отсутствие маркера).
Добавьте в окно приложения новую панель и нанесите на нее три переключателя, с именами rbMarkCifc, rbMarkSq, rbMarkNone, и надписями – «маркеры-круги», «маркеры-квадраты», «без маркеров» соответственно.
Состояние переключателя определяется его свойством Value: если Value равно единице, то переключатель включен. Задайте в редакторе свойств значение 1 свойству Value переключателя с надписью без маркеров - он будет включен при запуске программы.
Сохраняем ссылки на переключатели (логически группируем) и их значения в контексте формы в Листинге 7.
Листинг 8. mygui.m:
function GuiProj_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
optionsList = [ handles.rbMarkNone handles.rbMarkSq handles.rbMarkCifc ];
optionsValues = [ 'n' 's' 'o' ];
setappdata(hObject, 'optionsList', optionsList);
setappdata(hObject, 'optionsValues', optionsValues);
Листинг 9. Код обработчиков переключателей. mygui.m:
function rbMarkCifc_Callback(hObject, eventdata, handles)
switchMarkers(hObject, handles);
changeMarker(handles);
function rbMarkSq_Callback(hObject, eventdata, handles)
switchMarkers(hObject, handles);
changeMarker(handles);
function rbMarkNone_Callback(hObject, eventdata, handles)
switchMarkers(hObject, handles);
changeMarker(handles);
Листинг 10. Функция изменяет маркер в соответствии с выбранным переключателем. changeMarker.m:
function changeMarker(handles)
try
thePlot = getappdata(handles.axMain, 'plot');
markers = getappdata(handles.figure1, 'optionsValues');
set(thePlot, 'Marker', markers(getMarkerValue(handles)))
catch
;
end
Листинг 11. Функция возвращает текущий маркер (функция обертка).
getMarkerValue.m:
function changeMarker(handles)
try
thePlot = getappdata(handles.axMain, 'plot');
markers = getappdata(handles.figure1, 'optionsValues');
set(thePlot, 'Marker', markers(getMarkerValue(handles)))
catch
;
end
Листинг 12. Функция возвращает текущий переключатель в указанной группе. getSelectedOption.m:
function index = getSelectedOption(hObjectList)
index = 1;
for counter = (1 : length(hObjectList))
if get(hObjectList(counter), 'value') == 1
index = counter;
return
end
end
Листинг 13. Делает указанный переключатель текущим в группе (функция обертка). switchMarkers.m:
function switchMarkers(hObject, handles)
switchOptions(getappdata(handles.figure1, 'optionsList'), hObject, handles);
Листинг 14. Делает указанный переключатель текущим в указанной группе. switchOptions.m:
function switchOptions(hObjectList, hObject, handles)
for counter = hObjectList(1, 1:length(hObjectList))
if counter == hObject
set(hObject, 'value', 1);
else
set(counter, 'value', 0);
end
end
Нам приходится реализовывать функции переключения опций и привязки значений, так как они отсутствуют в Matlab (Что говорит о плохом дизайне). Для простоты мы использовали функциональный подход.
3.4.3. Списки
Предоставьте пользователю возможность выбора цвета линии графика из раскрывающегося списка (Popup menu) - синий, красный, зеленый. Перейдите в режим редактирования и добавьте раскрывающийся список с именем pmColor, элементами которого являются строки «синий», «красный», «зеленый» (поле String в многострочном режиме).
Запустите приложение и убедитесь, что раскрывающийся список содержит требуемые элементы. Выбор различных строк пока не приводит к изменению цвета линии - требуется запрограммировать событие Callback раскрывающегося списка.
Листинг 15. Сохраняем вектор с цветами в контексте формы. mygui.m:
function GuiProj_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
optionsList = [ handles.rbMarkNone handles.rbMarkSq handles.rbMarkCifc ];
optionsValues = [ 'n' 's' 'o' ];
colors = ['b', 'r', 'g' ];
setappdata(hObject, 'colors', colors);
setappdata(hObject, 'optionsList', optionsList);
setappdata(hObject, 'optionsValues', optionsValues);
Листинг 16. Внесите вызов ChangeColor в обработчик списка. mygui.m:
function pmColor_Callback(hObject, eventdata, handles)
changeColor(handles)
Листинг 17. Изменение цвета линии. ChangeColor.m:
function changeColor(handles)
try
thePlot = getappdata(handles.axMain, 'plot');
colors = getappdata(handles.figure1, 'colors');
set(thePlot, 'Color', colors(get(handles.pmColor, 'value')))
catch
;
end
3.4.4. Полосы прокрутки
Предоставив пользователю возможность устанавливать ширину линии при помощи полосы скроллинга. Добавьте полосу скроллинга (Slider) в окно приложения и задайте название scrWidth. Снабдите полосу текстовым пояснением «Толщина линии».
Теперь следует определить соответствие между положением бегунка полосы и числовым значением свойства Value.
Выполните следующие установки из редактора свойств:
-
В Мах занесите десять, а в Min - единицу. Свойства Мах и Min полосы скроллинга отвечают за границы значений, записываемых в Value, при перемещении бегунка.
-
Определите начальное положение бегунка полосы. Нажмите кнопку в строке с названием свойства и в появившемся окне Value измените значение на единицу.
-
Обратитесь к свойству SliderStep. Его значением является вектор из двух компонентов, первый из которых определяет относительное изменение Value при нажатии на кнопки со стрелками полосы скроллинга, а второй - при перетаскивании бегунка мышью. Следует установить значение [0.1 0.2] и нажатие на кнопки полосы изменит Value на десять процентов, а щелчок мыши справа или слева от бегунка на двадцать. Раскройте строку SliderStep щелчком мыши по знаку плюс слева от названия свойства и в появившихся строках х и у введите 0.1 и 0.2.
Листинг 18. Изменение толщины линии. mygui.m:
function scrWidth_Callback(hObject, eventdata, handles)
% Перехватываем исключительную ситуцию, например plot еще не
% инициализирован
try
thePlot = getappdata(handles.axMain, 'plot');
set(thePlot, 'LineWidth', round(get(hObject, 'value')))
catch
% действий не требуется
end;
3.4.5. Область ввода текста
Обычные текстовые области, использовавшиеся на протяжении предыдущих разделов, позволяют лишь вывести некоторый текст в окно приложения. Обмен текстовой информацией между пользователем и приложением осуществляется при помощи областей ввода текста. Предоставьте пользователю возможность размещать заголовок на графике.
Добавьте в окно приложения область ввода текста (Edit Text), с именем «editTitle» и снабдите ее пояснением в текстовой области, расположенной выше. Измените значение текстового поля по умолчанию на пустое.
Листинг 19. Изменение заголовка графика
function editTitle_CreateFcn(hObject, eventdata, handles)
if ispc
set(hObject,'BackgroundColor','white');
else
set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end
function editTitle_Callback(hObject, eventdata, handles)
title(get(hObject, 'String'))