【问题标题】:Defining MATLAB GUI default values before object creation在创建对象之前定义 MATLAB GUI 默认值
【发布时间】:2016-02-05 05:26:21
【问题描述】:

我喜欢在创建 GUI 对象之前定义变量(例如Appdata)。我在网上找不到以下问题:

  • 一般问题 1) 是什么决定了不同对象创建函数_CreateFcn 的执行顺序,还是它们都并行运行?

  • 一般问题 2) OpeningFcn 在对象创建后 运行。是否有对象创建之前运行的函数?

  • 具体问题:我的目标是记住 GUI 的属性值。因此,在更改属性(例如通过回调)并关闭 GUI 后,它应该在再次启动 GUI 后记住这些属性。如果是第一次启动 GUI,或者如果所有 appdata 都已重置,则应使用默认值。

目前(它有效)我为每个 _createFcn 定义了这些属性值(参见示例代码),但是对于 20 多个创建函数,它非常麻烦。是否可以在创建对象之前定义我的默认 appdata,这样我就不需要那么多 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

【问题讨论】:

    标签: matlab user-interface matlab-guide matlab-deployment appdata


    【解决方案1】:

    对于您的具体问题,您可以 1) 在 GUI 关闭之前将会话数据保存到 .mat 文件中,并在下次启动 GUI 时加载它,或者 2) 在 GUI 关闭之前将会话数据输出到工作区, 并在下次启动 GUI 时将其作为参数传递给 GUI 函数。这是一个代码 sn-p,它实现了一个名为test 的非常简单的 GUI 的两个选项,它是通过 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 按钮关闭 GUI 时,会调用默认的 CloseRequestFcn。默认版本只做一件事:杀死 GUI。在上述情况下,我们在OpeningFcn 中启用uiwait 以使程序等待用户响应(在这种情况下关闭GUI)。然后在CloseRequestFcn 中,uiresume 将 GUI 定向到 OutputFcn,然后将数据传递给 varargout 并终止 GUI。

    您可以通过两种方式使用 GUI,或者直接运行而不使用参数,或者

    output = test(input)
    

    如果没有参数,您在编辑文本框中键入的任何内容都将存储在sessiondata.mat 中,并在您下次启动 GUI 时加载。如果您为函数提供参数,它将使用此参数来更改编辑文本框中的文本。输出参数将是您关闭 GUI 之前留在编辑文本框中的任何文本。

    一般问题 1 的答案:这主要是我的猜测。如果您使用 GUIDE,我认为这取决于您创建对象的顺序。此信息存储在.fig 文件中。我做出这个猜测是因为 GUIDE 显然正在跟踪对象的创建,并且信息未存储在 .m 文件中。

    一般问题 2 的答案:CreateFcngui_mainfcn 的一部分,据说这是在 GUI 创建期间执行的第一个函数。虽然OpeningFcn 在对象创建之后运行,但它在 GUI 可用于用户交互之前执行,因此您可以在OpeningFcn 中设置您的 GUI。您也可以尝试更改每个对象的CreateFcn,但您必须在每个CreateFcn 中放置代码。所以,我认为OpeningFcn 将是您设置 GUI 的更好地方。

    【讨论】:

    • 很抱歉我的回复晚了,但感谢您的反馈!您提到我可以使用 .mat' 文件或工作区来存储我的 GUI 会话。但是,这不是问题,因为我将所有内容都存储在 appdata(0) 中。我想在对象创建之前 加载此会话的原因是因为每个对象CreateFcn 都使用此信息。您对一般问题的 2 个回答让我意识到从 CreateFcn 中删除所有代码并在 OpeningFcn 期间定义所有内容会更可靠。我需要先弄清楚如何使用handles,然后我会在这里更新我的工作!
    • 除非我弄错了,否则一旦你的 GUI 关闭,appdata 就会丢失。它用于在 GUI 处于活动状态时在回调之间共享数据。如果您希望在 GUI 执行期间生成信息,则需要永久性方法,例如将数据保存在文件中或工作区中的变量中。
    • 在我的情况下,只要 Matlab 本身打开,appdata 就会被存储。因此,每次在一天开始时启动 Matlab 时,它只能使用默认值,这对我来说很好。也许我没有使用appdata,因为它是“应该”使用的。将我的所有(全局)变量存储在其中似乎很方便。
    • 我想您也将appadata 声明为全局变量?我所指的appdata 是使用setappdata 方法与handles 结构一起存储的数据。如果您将这些信息存储为全局变量,那么它当然会在 GUI 会话之外持续存在,因为它存在于全局空间中,而不是每次运行时都会创建和销毁的 GUI 工作空间。我必须提醒您,强烈建议不要为此使用全局变量,因为您可以轻松地覆盖内置函数,甚至不会注意到它。
    • 我做了一些研究,结果发现appdata(0) 是 Matlab 的根工作区,因此确实是一个全局变量。来源:'*.com/questions/18330949/…'。我知道全局变量通常是个坏主意,但我并没有立即看到appdata(0) 的问题。在Matlab开始时它实际上是空的,因此没有被集成的matlab代码使用?