MATLAB和全局变量的使用?

时间:2012-02-02 20:28:10

标签: oop matlab dicom coupling

我正在编写一个用于dicom图像和光谱学的工具,我想在我正在制作的函数之间使用很多共享数据。我有GUI,不同的滑块和按钮使用了dicom文件中的大量共享数据。

我一直在使用全局变量来存储所有这些函数共享的信息。我目前有很多全局变量。如果可能的话,我被教导要避免全局变量,因为耦合增加了。在每个函数中读取dicom文件中的数据会更好吗?这似乎是多余的。将MATLAB用作面向对象的帮助吗?

5 个答案:

答案 0 :(得分:6)

我建议使用application data结构。

应用程序数据是存储为由应用程序定义的结构的基本数据,通常附加到GUI应用程序或图形窗口。

要使用应用程序数据(appdata),请使用setappdatagetappdata函数。例如,假设您有一个存储为hGUI的GUI句柄,下面将一个随机矩阵添加到您的应用程序数据中,然后再检索它(从MATLAB文档中取出)

% Save matrix for later
matrix = randn(35);
setappdata(hGUI, 'mydata', matrix);

% Do some stuff...

% Retrieve my matrix, this could be in a different file to `setappdata`
myMatrix = getappdata(hGUI, 'mydata');

您可以在应用程序数据中存储基本上任意的数据,只要hGUI引用您的GUI应用程序,您就可以存储它并从任何源文件中获取它。

答案 1 :(得分:4)

由于您提到您正在使用GUI 想要在控件回调之间共享数据,我建议您使用nested functions设计代码。整体代码看起来像这样:

function dicomGUI

  %# Initialize your GUI here, linking the control callbacks to the
  %#   nested functions below:

  hLoad = uicontrol('Style', 'push', 'String', 'Load file', ...
                    'Callback', @load_file);
  ...

  %# Initialize the data variables for the DICOM files here:

  data = [];  %# Shared among nested functions
  ...

  %# Below are all the nested functions your controls will use:

  function load_file(hSource, event)
    data = ...;  %# Load the data here
  end
  ...

end

这不仅可以让您将所有GUI代码放在一个m文件中,而且还可以简化控件回调,并使它们可以轻松地在父函数dicomGUI的工作空间中共享变量。可以在此文档页面上找到此方法的示例以及GUI控件之间共享数据的其他建议:Share Data Among a GUI's Callbacks

正如克里斯所提到的,这可能会成为一个非常大的m文件,用于庞大而复杂的GUI。为了在这种情况下保持文件大小,我建议将每个回调的主体简单地调用一个单独的文件中的函数,该文件接受共享数据变量,执行任何必要的工作,然后将修改后的数据返回到相同的共享变量。例如:

function transform_callback(hSource, event)

  %# Apply some transform to the data:
  data = transform_data(data);

  %# If the above changes the GUI (disabling controls, changing a
  %#   display, etc.), then those changes should be made here.

end

答案 2 :(得分:2)

全球通常是一件坏事。通常有几种更好的方法,包括:

  1. 最初读取数据,并将其传递给需要它的每个函数。
  2. 读取数据,需要它的每个函数调用一个返回它的函数。
  3. 您可能还需要在返回时以某种方式更新数据包,具体取决于您是仅使用数据还是更改数据以及使用数据。

    这些想法中的任何一个都应该有助于您的过程。它使您的代码更具可读性,并且不太可能出现某种错误。

答案 3 :(得分:2)

由于MATLAB的面向对象性质,还有另一种可能性。您可以定义自己的句柄类,并在初始化阶段将其作为附加参数传递给每个回调:

classdef Data<handle
    properties (Access=public)
        Val;
    end
end

function SimpleGui
    data = Data();

    hLoad = uicontrol('Style', 'push', 'String', 'Push me', ...
                      'Callback', {@callback data});
    data.Val = 5;
end

function callback(hSource, event, data)
    data.Val = data.Val+1;
    disp(data.Val);
end

另一种选择:

此外,关于guidata / appdata(如@Chris所述),可以通过以下方式进行改进:

创建一个始终获取并设置guidata的封装回调:

function CallbackWrapper(hObj,evt,func)
    data = guidata(hObj);
    data = func(hObj,evt,data);
    guidata(hObj,data);
end

现在你的回调应该按照以下方式定义(注意不同的签名):

function SimpleGui
    hSave = uicontrol('Style', 'push', 'String', 'Push me', ...
        'Callback', {@CallbackWrapper @myCallBack});
    data.x = 1;
    guidata(hSave,data);
end

function data = myCallBack(hObj,evt,data)
    data.x = data.x + 1;
    disp(data.x);
end

答案 4 :(得分:0)

如果您使用的是MATLAB的更高版本之一,则应该利用OOPS(面向对象编程系统)。

您应该遵循软件设计原则,并从构建合理的软件设计开始。您应该在编写任何代码之前执行此操作。我建议使用UML进行软件建模。