Определение значений по умолчанию MATLAB GUI перед созданием объекта

Мне нравится определять переменные (например, Appdata) перед созданием объектов GUI. Не сразу нашел в сети следующие вопросы:

  • Общий вопрос 1) Что определяет порядок выполнения различных функций создания объектов _CreateFcn или все они выполняются параллельно?

  • Общий вопрос 2) OpeningFcn запускается после создания объекта. Есть ли функция, которая запускается перед созданием объекта?

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

На данный момент (это работает) я определяю значения этих свойств для каждого отдельного _createFcn (см. пример кода), но для 20+ функций создания это очень громоздко. Можно ли определить мои данные приложения по умолчанию перед созданием объекта, чтобы мне не нужно было так много циклов if? (см. пример кода 2)

пример кода 1 (текущая ситуация):

% --- Executes during object creation, after setting all properties.
function checkbox_res_mot_CreateFcn(hObject, eventdata, handles)
% hObject    handle to checkbox_res_mot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called
if isappdata(0,'Simulation')     %check if appdata exists
  simulation = getappdata(0,'Simulation');
  if  any(strcmp(fieldnames(simulation),'residual_motions'))     %check if variable exists
      set(hObject,'Value',simulation.residual_motions);     % stored value
  else
      set(hObject,'Value',0);    % default value
  end
else
  set(hObject,'Value',0);    % default value
end
simulation.residual_motions = get(hObject,'Value');      % create appdata
setappdata(0,'Simulation',simulation)

пример кода 2 (предложение):

%Executs before object creation
function default_values
if ~isappdata(0,'Simulation')
simulation.residual_motions = 0          % default values all in same function (only 1 variable shown as example)
setappdata(0,'Simulation',simulation)    % create appdata

%% --- Executes during object creation, after setting all properties.
function checkbox_res_mot_CreateFcn(hObject, eventdata, handles)
% hObject    handle to checkbox_res_mot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called
simulation = getappdata(0,'Simulation');        % no need to check appdata as it has already been created
set(hObject,'Value',simulation.residual_motions);    % residual_motions has been created in 'default value' code or is saved from last GUI execution

person Remco    schedule 04.11.2015    source источник


Ответы (1)


Для вашего конкретного вопроса вы можете либо 1) сохранить данные сеанса в файл .mat до закрытия графического интерфейса и загрузить его при следующем запуске графического интерфейса, либо 2) вывести данные сеанса в рабочую область до закрытия графического интерфейса и передать их в Функция GUI в качестве аргумента при следующем запуске GUI. Вот фрагмент кода, который реализует обе опции для очень простого графического интерфейса с именем test, который создается с помощью GUIDE и имеет в нем одно текстовое поле редактирования.

function test_OpeningFcn(hObject, eventdata, handles, varargin)
if ~isempty(varargin)
    set(handles.edit1, 'String', varargin{1})
elseif exist('sessiondata.mat','file')
    temp_data = load('sessiondata.mat','output');
    set(handles.edit1, 'String', temp_data.output) 
end
guidata(hObject, handles);
uiwait(handles.figure1);

function varargout = test_OutputFcn(hObject, eventdata, handles) 
output = get(handles.edit1, 'String');
varargout{1} = output;
save('sessiondata.mat', 'output')
delete(handles.figure1);

function figure1_CloseRequestFcn(hObject, eventdata, handles)
uiresume(hObject);

Обычно, когда вы нажимаете кнопку X, чтобы закрыть графический интерфейс, вызывается CloseRequestFcn по умолчанию. Версия по умолчанию делает только одно: убивает графический интерфейс. В приведенном выше случае мы включаем uiwait в OpeningFcn, чтобы программа ждала ответа пользователя (в данном случае это закрытие графического интерфейса). Затем в CloseRequestFcn uiresume направляет графический интерфейс на OutputFcn, который затем передает данные на varargout и убивает графический интерфейс.

Вы можете использовать графический интерфейс двумя способами: либо просто запустить его без аргументов, либо

output = test(input)

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

Ответ на общий вопрос 1: Это в основном мое предположение. Я думаю, это определяется порядком, в котором вы создаете объекты, если используете GUIDE. Эта информация хранится в файле .fig. Я делаю это предположение, потому что GUIDE, по-видимому, отслеживает создание объекта, а информация не хранится в файле .m.

Ответ на общий вопрос 2: CreateFcn является частью gui_mainfcn, которая предположительно является первой функцией, выполняемой при создании GUI. Хотя OpeningFcn запускается после создания объекта, он выполняется до того, как графический интерфейс становится доступным для взаимодействия с пользователем, поэтому вы можете настроить свой графический интерфейс в файле OpeningFcn. Вы также можете попробовать изменить CreateFcn для каждого объекта, но вам придется размещать коды в каждом CreateFcn. Итак, я думаю, что OpeningFcn будет лучшим местом для настройки вашего графического интерфейса.

person user3667217    schedule 04.11.2015
comment
Извините за мой поздний ответ, но спасибо за ваш отзыв! Вы упомянули, что я могу использовать файлы .mat или рабочее пространство для хранения своего сеанса графического интерфейса. Однако это не было проблемой, так как я хранил все в appdata(0). Причина, по которой я хотел загрузить этот сеанс до создания объекта, заключается в том, что каждый объект CreateFcn использует эту информацию. Ваши 2 ответа на общие вопросы заставили меня понять, что будет надежнее удалить весь код из CreateFcn и определить все во время OpeningFcn. Сначала мне нужно выяснить, как работать с handles, а потом я обновлю свою работу здесь! - person Remco; 10.11.2015
comment
Если я не ошибаюсь, appdata будет потерян, как только ваш графический интерфейс будет закрыт. Он предназначен для обмена данными между обратными вызовами, когда графический интерфейс жив. Если вы хотите, чтобы информация генерировалась во время выполнения графического интерфейса, вам потребуются постоянные средства, такие как сохранение данных в файле или переменной в рабочей области. - person user3667217; 10.11.2015
comment
В моем случае appdata сохраняется до тех пор, пока открыт сам Matlab. Поэтому каждый раз, когда Matlab запускается в начале дня, он может использовать только значения по умолчанию, и меня это устраивает. Может быть, я не использую appdata, поскольку он «предполагается» для использования. Просто кажется таким удобным хранить в нем все мои (глобальные) переменные. - person Remco; 11.11.2015
comment
Я полагаю, вы также объявляете appadata глобальной переменной? appdata, о котором я говорю, — это данные, хранящиеся вместе со структурой handles с использованием метода setappdata. Если вы сохраните эту информацию как глобальную переменную, то, конечно, она будет сохраняться за пределами сеанса графического интерфейса, потому что она живет в глобальном пространстве, а не в рабочем пространстве графического интерфейса, которое создается и уничтожается каждый раз, когда вы его запускаете. Я должен напомнить вам, что использование глобальной переменной для этой цели настоятельно не рекомендуется, потому что вы можете легко переопределить встроенную функцию, даже не заметив этого. - person user3667217; 12.11.2015
comment
Я провел небольшое исследование, и оказалось, что appdata(0) — это корневая рабочая область Matlab и, следовательно, действительно глобальная переменная. Источник: 'stackoverflow.com/questions/18330949/'. Я знаю, что глобальные переменные, как правило, плохая идея, но я не сразу вижу проблему для appdata(0). В начале Matlab он фактически пуст, поэтому не используется интегрированными кодами Matlab? - person Remco; 12.11.2015
comment
хм. На самом деле я ничего не знаю о setappdata(0, m). Спасибо, что поделились этим. Тем не менее, если есть другое решение, например два, которые я предложил в своем ответе, избегайте использования глобальной переменной. Это трудно отследить. Я не осознавал этого, когда впервые изучал MATLAB. Постепенно мне это стало ясно. - person user3667217; 12.11.2015