MATLAB.Exponenta
–Û·Ë͇ Matlab&Toolboxes

Приложения с GUI и дескрипторная графика

Использование указателей при работе с графическими объектами

При работе с графикой в MATLAB часто возникают следующие вопросы:

  • Есть несколько графических окон и пар осей. Как вывести график на нужные оси в нужное графическое окно?
  • Как удалить ненужный графический объект, например окно, оси, линию и т.д.?
  • Как изменить свойства одного из нескольких имеющихся объектов, например цвет линии, многоугольника, размер шрифта текста и т.д.
  • Как создать копию объекта, например, на одних осях есть линия, как скопировать ее на другие оси?
  • Как найти нужные объекты для изменения их свойств, например, как изменить цвет всех красных линий на зеленый?
  • Как предотвратить случайное изменение графического окна пользователем?

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

Об указателях

В MATLAB при создании графического объекта ему присваивается указатель, обычно это вещественное число (про исключения сказано ниже). Предположим, что мы создали графическое окно и оси

>> figure
>> axes

и теперь хотим построить график функции y=x2 , скажем на отрезке [-1,1.5] . Для этого заполним массивы x и y.

>> x = -1 : 0.1 : 1.5;
>> y = x.^2;

а затем построим график, вызвав функцию plot с выходным аргументом

>> h = plot(x, y)

Функция plot возвращает указатель на линию, которым можно пользоваться, если требуется изменить свойства линии. Например, по умолчанию, функция plot строит первый график линией синего цвета. Если мы хотим изменить цвет линии, например на красный, то достаточно вызвать функцию set с парой аргументов ‘НазваниеСвойства', значение:

>> set(h, 'Color', 'r')

Свойства линий подробно описаны здесь.

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

В предыдущем примере можно было сохранить указатель не только на линию, но и на создаваемое графическое окно и оси. Для этого следовало вызвать функции figure и axes с выходным аргументом:

>> hF = figure
>> hA = axes

Тогда в переменную hF записывается указатель на графическое окно, а в переменную hA — указатель на оси. И пока графическое окно не было удалено, или закрыто, можно изменять его свойства, например цвет:

>> set(hF, 'Color', 'w')

В MATLAB по умолчанию указатели на графические окна являются целыми числами, присваиваемыми графическим окнам в порядке их создания. Например, если уже создано два графических окна (любым способом: функцией figure, при помощи меню File – New - Figure), то функция

>> hF = figure

вернет

hF = 3

Значение указателя на графическое окно совпадает с его номером, который записан в строке заголовка окна после слова Figure.

Иногда целочисленный указатель может служить источником ошибок, например,

>> set(1, ‘Color’, ‘r’)

приведет к изменению цвета первого графического окна, если есть хотя бы одно графическое окно, или к ошибке, если графических окон нет.

Про то, как сделать указатель на графическое окно вещественным, или вообще скрыть указатель на окно, сказано в разделе Указатели на окна.

Целочисленными могут быть указатели не только на графические окна. Так, целочисленный указатель равный нулю указывает на корневой объект Root. Объект Root может быть использован для задания или получения некоторых глобальных параметров MATLAB, например, для получения размера монитора в пикселях достаточно выполнить

>> s = get(0, 'ScreenSize')

Более подробно про свойства корневого объекта написано в разделе Использование корневого объекта Root.

В следующем разделе мы обсудим организацию структуры графических объектов в MATLAB, понимание которой необходимо для эффективной работы.

Про иерархию объектов, отличие Core Object от Plot Object и про разные текстовые объекты

Предположим, что в данный момент нет ни одного графического окна. Выполним команды

>> x = -1 : 0.1 : 1.5;
>> y = x.^2;
>> h = plot(x, y)

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

В MATLAB все графические объекты выстроены в определенную иерархию. На вершине иерархии — корневой объект Root, ему может принадлежать одно или несколько графических окон. Каждому из графических окон может принадлежать одна или несколько пар осей, а уже осям принадлежат объекты самого низкого уровня: линии, поверхности, многоугольные объекты, текстовые объекты, изображения и источники света.

Каждый из объектов создается своей функцией, например многоугольный объект создается при помощи функции patch. Функции для создания графических объектов перечислены в справочной системе в разделе MATLAB: Graphics: Core Graphics Objects. В начале этого раздела приведена таблица с названиями функций, которые являются гиперссылками на соответствующие страницы с их описанием. Может показаться странным, что на этой странице справочной системы есть функция line, однако отсутствует функция plot, которая, по-существу, также строит линию. Дело в том, что начиная с 7-ой версии в MATLAB различаются:

  • базовые объекты (Core Objects), которые создаются именно перечисленными на этой странице справочной системы функциями;
  • рисованные объекты (Plot Objects), которые создаются функциями типа plot, plot3, mesh и т.д.

Рассмотрим простой пример, чем отличаются линии, созданные при помощи функций line и plot.

Во-первых, сами функции работают по-разному. Функция line добавляет линию на оси, а функция plot удаляет предыдущее содержимое и затем рисует линию (если не принято специальных мер, вроде команды hold on или изменения значения свойства NextPlot осей).

Во-вторых, функция line создает базовый объект типа line, а функция plot (или plot3) создает рисованный объект lineseries. Рисованные объекты обладают такими свойствами, которых нет у соответствующих им базовых объектов. Например, у объекта lineseries есть свойства DisplayName, XDataSource, YDataSource и ZDataSource, отсутствующие у объекта line. Свойство DisplayName служит для отображения в легенде соответствующего имени, а XDataSource, YDataSource и ZDataSource позволяют связать линию с именами массивов данных, по которым будет производится построение графика.

Приведем пример. Скажем, у нас заданы вектора x и y одинаковой длины, но компоненты вектора y изменяются в процессе вычислений. Мы хотим получать все время обновленные графики, причем не удаляя старый график и выводя новый, а изменяя свойства линии.

При помощи функции plot и, соответственно, рисованного объекта lineseries эта задача может быть решена следующим образом.

% создаем графическое окно и оси
figure
axes
% задаем вектор x и начальный вектор y
x = -1:0.01:3;
y = sin(x);
% строим график, указатель на объект lineseries записываем в переменную h
h = plot(x,y);
% задаем имя  y в качестве значения свойств YDataSource
set(h, 'YDataSource', 'y')
% в цикле изменяем компоненты y
for a = 1 : 10 
    % вычисляем элементы нового вектора y
    y = sin(a*x);
    % обновляем данные
    refreshdata(h)    
    % делаем паузу в 0.5сек.
    pause(0.5)
end

В этом примере использована функция refreshdata, обновляющая данные, по которым построена линия графика.

Решим эту же задачу с использованием функции line и, соответственно, создаваемого ей объекта line. Для построения линии можно, например, задать в качестве значений свойств XData и YData исходные массивы, а затем в цикле изменять значение свойства YData на обновленный массив.

% создаем графическое окно и оси
figure
axes
% задаем вектор x и начальный вектор y
x = -1:0.01:3;
y = sin(x);
% создаем линию (объект line) при помощи функции line и свойств XData, YData
% и записываем указатель на нее в переменную h
h = line('XData', x, 'YData', y)
for a = 1 : 10 
    % вычисляем элементы нового вектора y
    y = sin(a*x);
    % задаем новое значение свойству YData линии 
    set(h, 'YData', y)
    % делаем паузу в 0.5сек.
    pause(0.5)
end

Более подробно при иерархию графических объектов и про новшества, появившиеся начиная с 7-ой версии, написано в разделе Иерархия графических объектов

С текстовыми объектами нередко возникает путаница. Дело в том, что есть два типа текстовых объектов.

  1. Создается при помощи функции text и принадлежит осям в иерархии графических объектов.
  2. Создается при помощи функции uicontrol и в иерархии принадлежит графическому окну. Этот тип текстового объекта часто используется при создании приложений с графическим интерфейсом пользователя (в качестве надписи, например рядом с областью ввода).

Важно понимать, что если текстовый объект создан функцией text (и, следовательно, принадлежит осям в иерархии графических объектов, то он не обязательно должен находится в пределах осей). Рассмотрим такой пример, в котором создаются оси (по умолчанию они двумерные и пределы по каждой из осей [0, 1]) и текстовый объект с координатами левого нижнего угла (0.2, -0.1):

>> figure
>> axes
>> text(0.2,-0.1, 'This text is the descendant of the axes')


Текстовый объект — потомок осей (функция text)

Текстовый объект, созданный при помощи функции text, существует только если существуют оси, которым он принадлежит. При удалении осей тестовый объект так же будет удален. Кстати, создаваемый функцией title заголовок является текстовым объектом — потомком осей. Функция title может быть вызвана с выходным аргументом, в который записывается указатель на создаваемый заголовок

>> figure
>> axes
>> hT = title('The title')

Этот указатель может быть использован впоследствии для форматирования заголовка, например для изменения цвета шрифта

>> set(hT, 'Color', 'r')

Рассмотрим теперь текстовый объект второго типа, который получается в результате вызова функции uicontrol и вовсе не требует наличия осей. Обязательно только существование графического окна.

>> figure
>> uicontrol('Style', 'text', 'position', [10 10 300 20],...
    'String', 'Example of static text')


Текстовый объект — потомок графического окна (функция uicontrol)

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

Текущее графическое окно и текущие оси

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

  1. только что созданы;
  2. сделаны текущими щелчком мыши по ним;
  3. сделаны текущими при помощи функций axes или subplot.

Первый случай очевиден. Например, если есть несколько графических окон, то последовательность команд

>> figure
>> axes
>> surf(peaks(30))

приведет к выводу поверхности именно на созданные только что оси.

Со вторым случаем тоже все достаточно просто. Если созданы два графических окна, каждое со своей парой осей,

>> figure
>> axes
>> figure
>> axes

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

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


Создание нескольких пар осей при помощи панели Figure Palette.

Оси добавляются в режиме интерактивного редактирования при помощи 2D Axes или 3D Axes (раздел New Subplot), их размеры и положение меняются при помощи мыши. Для выхода из режима редактирования следует отжать кнопку Edit Plot на панели инструментов графического окна.

Несколько пар осей в одном графическом окне могут быть созданы и программно, например с использованием функции subplot. В самом простом случае предполагается, что выбран способ разбиения графического окна на оси, например 3 по вертикали и 2 по горизонтали. Эти числа (способ разбиения) указываются в качестве первых двух входных аргументов функции subplot. Третьим входным аргументом задается номер пары осей, причем оси нумеруются слева направо и сверху вниз.

Например следующие команды

>> figure
>> subplot(3,2,2)
>> subplot(3,2,3)
>> subplot(3,2,5)

приводят к созданию графического окна и трех пар осей: 2-ой, 3-ей и 5-ой.


Создание осей при помощи функции subplot.

Разумеется, последовательные шесть обращений к функции subplot: subplot(3, 2, 1), subplot(3, 2, 2), subplot(3, 2, 6) приведут к созданию всех шести пар осей. Но не обязательно создавать оси по порядку. При этом последняя из созданных пар осей становится текущей и именно на нее произойдет графический вывод. Если же требуется сделать существующую пару осей текущей, то достаточно снова вызвать subplot, указав те же самые первые два входных аргумента для способа разбиения и номер нужной пары осей в третьем входном аргументе функции subplot.

Функция subplot предоставляет еще ряд возможностей:

  • удаление пары осей и создание вместо нее другой пары осей;
  • нерегулярное разбиение графического окна на оси (например сверху окна длинные оси, а под ними еще две и т.д.);
  • расположение осей в произвольном месте окна с указанием их размеров.

Эти возможности описаны в справочной системе MATLAB

>> doc subplot

Для создания в графическом окне нескольких произвольно расположенных пар удобно применять функцию axes, которая позволяет задавать все свойства осей (см. раздел Свойства осей).

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

Вообще, лучше взять за правило: при создании графического объекта сохранять указатель на него. Это позволит получить полный контроль над графическими объектами. Например, если известен указатель на графическое окно, то в него легко добавить оси, сделав его текущим.

Как делать нужное графическое окно или оси текущими? Функция figure служит не только для создания графического окна, но и для того, чтобы сделать существующее окно текущим. Предположим, что было создано графическое окно и указатель на него сохранен в переменную hF1:

>> hF1 = figure;

После этого могли быть созданы и другие графические окна и выполнены другие действия. Если после этих действий графическое окно с указателем hF1 не было закрыто, то для того, чтобы оно стало текущим, достаточно выполнить

>> figure(hF1)

Аналогично, функция axes служит не только для создания осей, но и для выбора текущих осей, указатель на которые должен быть задан в ее входном аргументе.

Рассмотрим пример, в котором требуется выводить графики на четыре пары осей, расположенных в двух графических окнах. Сначала создадим два графических окна, а затем оси в них, делая перед созданием осей нужное графическое окно текущим при помощи функции figure. Для указания положения и размеров осей воспользуемся их свойством Position, значением которого является вектор из четырех компонент

[x y width height]

где x и y — координаты левого нижнего угла осей относительно левого нижнего угла графического окна, width — ширина осей, а height — их высота. Все величины задаются по умолчанию в так называемых «нормализованных» единицах. Это значит, что высота и ширина графического окна принимаются равными единице, а x, y, width и height задаются в долях единицы. После создания всех осей будем последовательно делать нужную пару текущей и выводить на нее графики функций двух переменных при помощи ezsurf и ezmesh.

% создаем первое и второе графическое окно
hF1 = figure;
hF2 = figure;
% делаем первое графическое окно текущим
figure(hF1)
% создаем в первом окне нижнюю пару осей
hA11 = axes('Position', [0.1 0.1 0.8 0.35])
% создаем в первом окне верхнюю пару осей
hA12 = axes('Position', [0.1 0.6 0.8 0.35])
% делаем второе графическое окно текущим
figure(hF2)
% создаем во втором окне левую пару осей
hA21 = axes('Position', [0.1 0.1 0.35 0.8])
% создаем во втором окне правую пару осей
hA22 = axes('Position', [0.6 0.1 0.35 0.8])
% делаем в первом окне нижние оси текущими и выводим на них график
axes(hA11)
ezsurf('sin(x)*cos(2*y)')
% делаем в первом окне верхние оси текущими и выводим на них график
axes(hA12)
ezsurf('sin(x)-cos(y)')
% делаем во втором окне левые оси текущими и выводим на них график
axes(hA21)
ezmesh('sin(x)*sinh(y)')
% делаем во втором окне правые оси текущими и выводим на них график
axes(hA22)
ezmesh('cosh(x)/cosh(y)')

В результате получаем

При наличии достаточно большого числа окон и осей указатели на них лучше хранить в массивах.

Как мы уже замечали, указатели на окна являются по умолчанию целыми числами, что может привести к случайному изменению содержимого окна. В следующем разделе рассматривается вопрос о предотвращении случайного изменения содержимого графического окна.

Указатели на окна, как сделать так, чтобы MATLAB «не видел» графическое окно

Итак, по умолчанию, при создании графического окна его указатель получает целочисленное значение. Следовательно, команда

set(n, ‘СвойствоОкна’, значение)

приведет к изменению значения некоторого свойства графического окна (разумеется, если окна с номером n нет, то выведется сообщение об ошибке). Вопрос о присваивании указателю вещественного значения решается достаточно просто. Для этого следует установить свойству IntegerHandle значение 'off'. Естественно, данное действие выполняется при создании графического окна:

>> hF = figure('IntegerHandle', 'off')
hF =
  153.0352

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

Возникает вопрос, как же сделать графическое окно «невидимым» для MATLAB (но вовсе не для пользователя). Это бывает нужно, когда некоторое приложение вывело результат в графическом окне и требуется запретить пользователю изменять его содержимое вводимыми командами. Для того, чтобы сделать окно «невидимым» для MATLAB следует установить его свойство HandleVisibility в значение ‘off’, т.е. скрыть указатель на окно:

hF = figure
axes
ezsurf('sin(x)*cos(2*y)')
set(hF, 'HandleVisibility', 'off') 

Теперь следующие команды графического вывода «не заметят» это окно и создадут новое или выведут результат в какое-то другое (существующее) окно, указатель на которое не является скрытым.

Скрытие указателя не мешает доступу к свойствам окна по указателю, т.е. в приведенном выше примере

set(hF, ‘СвойствоОкна’, значение)

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

Не следует путать скрытие указателя на графическое окно и скрытие самого окна. Для скрытия графического окна его свойство Visible устанавливают в значение ‘off’ (по умолчанию оно принимает значение ‘on’). При скрытии окна оно действительно становится невидимым, но не MATLAB’у, а пользователю. В этом нас убеждает следующий пример. В нем создается графическое окно и оси, на которые выводится поверхность. Далее окно делается невидимым (оно все еще остается текущим, так же как и оси этого окна) и выполняется команда cla для очистки текущих осей. После этого графическое окно снова делается видимым и мы обнаруживаем, что график пропал.

% создаем графическое окно и оси
hF = figure
axes
% выводим поверхность
ezsurf('sin(x)*cos(2*y)')
% скрываем окно
set(hF,'Visible', 'off')
% очищаем текущие оси 
cla
% делаем окно видимым
set(hF, 'Visible', 'on')

Как определить, какой объект текущий

Как графическое окно и оси становятся текущими, мы выяснили в разделе Текущее графическое окно и текущие оси. Иногда возникает другая задача. Есть несколько окон, осей и графических объектов на них и требуется получить указатель на текущее окно, текущие оси или текущий объект.

Для получения указателя на текущее графическое окно служит функция gcf (сокращение от get current figure)

hF = gcf 

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

hF = get(0, 'CurrentFigure')

Теперь h либо пустой массив, либо указатель на текущее графическое окно.

Функция gca служит для получения указателя на текущие оси (сокращение от get current axes).

hA = gca

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

При непосредственном обращении

hA  = get(gcf, 'CurrentAxes')

в hA записывается указатель на текущие оси. Однако, если графических окон нет (или указатели на все окна скрыты), то сначала создастся графическое окно, т.к. в первом входном аргументе функции get стоит вызов функции gcf, а что происходит при обращении к gcf мы только что обсудили. Поэтому вместо gcf можно использовать get(0, 'CurrentFigure'). Итак, последовательность команд

hF = get(0, 'CurrentFigure')
hA = get(hF, 'CurrentAxes')

возвращает указатель на текущие оси или пустой массив, если осей нет. Можно объединить эти две команды в одну:

hA = get(get(0, 'CurrentFigure'), 'CurrentAxes')

Осталось выяснить, как определить указатель на текущий объект. Для этого есть функция gco (сокращение от get current object). Предположим, что на оси выведены графики двух функций:

% создание графического окна и осей
hF = figure
hA = axes
% заполнение массивов данных
x = linspace(0,2*pi,40);
f = sin(x);
g = cos(x);
% вывод графиков и сохранение указателей на линии в массиве hL
hL = plot(x, f, x, g)

В этом примере в вектор hL записаны указатели на линии графиков, т.к. функция plot возвращает указатели на все построенные линии. При вызове gco возможно несколько вариантов:

  1. Если вызвать gco сразу после выполнения вышеприведенных команд, то gco вернет пустой массив, т.к. ни по какому объекту не было сделано щелчка.
  2. Если сделать щелчок по одной из линий и вызвать gco, то вернется указатель на эту линию.
  3. Если сделать щелчок вне линий но в пределах осей и вызвать gco, то она вернет указатель на оси.
  4. Если сделать щелчок вне осей но в пределах графического окна и вызвать gco, то она вернет указатель на графическое окно.

Удаление графических объектов

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

Удаление графических окон может быть осуществлено также и при помощи функции close. Здесь может быть несколько вариантов:

close — удаляет текущее графическое окно.

close(hF) — удаляет графическое окно с указателем hF, если hF — массив указателей, то удаляются все соответствующие окна.

close(‘ИмяОкна’) или close ‘ИмяОкна’ — удаляет графическое окно с именем ‘ИмяОкна’. Что это значит? Дело в том, что графическому окну может быть задано имя, которое появляется в заголовке окна. Это можно сделать для существующего графического окна, установив при помощи функции set подходящее значение свойства Name, или, например, при создании окна:

>> figure('Name', 'The results')

Теперь окно может быть удалено следующим образом

>> close('The results')

close all — удаляет все имеющиеся графические окна, указатели на которые не являются скрытыми.

Для команды close с параметром all есть эквивалентная функциональная форма close(‘all’). Однако, если есть несколько графических окон и у одного из них имя all, то закроются все окна, а не только с именем all, например

>> figure('Name', 'all')
>> figure('Name', 'The results')
>> close('all')

close all hidden — удаляет все имеющиеся графические окна, включая окна со скрытыми указателями.

status = close(hF) — возвращает 1, если окно с указателем hF было удалено, и возвращает 0, если нет.

Может показаться странным, что предусмотрено значение status = 0, т.е. возникает вопрос, почему окно не может быть закрыто. Дело в том, что при закрытии окна при помощи close или кнопки с крестиком в верхнем правом углу на заголовке окна вызывается специальная функция closereq, которая и производит удаление окна. Текст этой функции можно посмотреть (не стоит только ее изменять):

>> edit closereq

Однако, можно назначить свою последовательность действий, выполняющихся при попытке закрытия графического окна. Для этого предназначено свойство окна CloseRequestFcn. По умолчанию при создании графического окна свойству CloseRequestFcn присваивается значение ‘closereq’, т.е. имя стандартной функции. Мы сами можем назначить нужную последовательность действий, выполняемых перед закрытием графического окна, если зададим в качестве значения свойства CloseRequestFcn некоторую команду или имя написанной нами функции.

Приведем пример, в котором при создании графического окна его свойство CloseRequestFcn получает значение 'errordlg(''You can not close this window'')'. Функция errordlg служит для вызова стандартного диалогового окна с сообщением об ошибке, сам текст указывается в ее входном аргументе в апострофах. Два идущих подряд апострофа в строке ''You can not close this window'' используются потому, что само значение свойства CloseRequestFcn должно быть заключено в апострофы, т.е. должно быть строкой, а если в строке встречается символ апостроф, то он должен быть задан при помощи двух апострофов.

>> hF = figure('CloseRequestFcn','errordlg(''You can not close this window'')')

Созданное графическое окно не может быть закрыто кнопкой с крестиком или командой close. Каждый раз при попытке закрытия окна работает функция errordlg, которая выводит сообщение и больше никаких действий не предпринимается. Для закрытия данного окна можно использовать функцию delete:

>> delete(hF)

В этом и состоит различие между delete и close в применении к графическим окнам. Удаление окна при помощи функции delete не приводит к выполнению действий, указанных в CloseRequestFcn.

При обработке закрытия окна можно выполнить и более полезное действие, чем просто запрещать его закрытие. Как правило, для этого нужно запрограммировать свою функцию. Например, в функции close_with_request выводится диалоговое окно подтверждения, в котором спрашивается, действительно ли нужно закрыть окно. Если пользователь нажал кнопку Yes, то окно закрывается.

function close_with_request
answer = questdlg('Are you sure?', 'Yes', 'No');
if isequal(answer, 'Yes')
    delete(gcf)
end

Теперь графическое окно, созданное при помощи

>> hF = figure('CloseRequestFcn','close_with_request')

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

В заключение приведем пример, в котором создается графическое окно, оси и 10 прямоугольников. Прямоугольники выводятся на оси при помощи функции rectangle, причем задаются случайные размеры прямоугольников (координаты левого нижнего угла, ширина и высота — случайные числа от 0 до 1). Для каждого создаваемого объекта его свойство ButtonDownFcn принимает значение 'delete(gco)'. Значение ButtonDownFcn определяет действия, выполняемые в результате щелчка мышью по объекту. Поскольку gco возвращает указатель на текущий объект, то щелчок по прямоугольнику приводит к его удалению. Аналогично, щелчок по осям приводит к удалению осей, а по графическому окну — к удалению окна.

figure('ButtonDownFcn', 'delete(gco)')
axes('ButtonDownFcn', 'delete(gco)')
for k = 1 : 10
    rectangle('Position',rand(1, 4),...
        'FaceColor',rand(1,3),...
        'ButtonDownFcn', 'delete(gco)')
end

Копирование графических объектов

Поиск графических объектов

Использование корневого объекта Root


Поиск по сайту:

Система Orphus

Яндекс.Метрика