MATLAB и использование глобальных переменных? - PullRequest
3 голосов
/ 03 февраля 2012

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

Я использовал глобальные переменные для хранения информации, которую разделяют все эти функции.У меня сейчас много глобалов.Меня учили избегать глобальных переменных, если это возможно, из-за растущей связи.Было бы лучше прочитать данные из файла dicom в каждой функции?Это кажется излишним.Будет ли использование MATLAB в качестве объектно-ориентированной справки?

Ответы [ 5 ]

6 голосов
/ 03 февраля 2012

Я бы рекомендовал использовать данные приложения структуры.

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

Чтобы использовать данные приложения (appdata), используйте функции setappdata и getappdata. Например, предполагая, что у вас есть дескриптор вашего GUI, сохраненный как hGUI, следующий код добавляет случайную матрицу к данным вашего приложения, а затем извлекает ее позже (поднято из документации 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 относится к вашему приложению с графическим интерфейсом.

4 голосов
/ 03 февраля 2012

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

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, можно найти на этой странице документации: Обмен данными среди обратных вызовов графического интерфейса .

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

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 голосов
/ 08 февраля 2012

Существует еще одна возможность из-за объектно-ориентированной природы 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
2 голосов
/ 03 февраля 2012

Глобалы, как правило, плохо.Обычно есть несколько способов, которые включают:

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

Возможно, вам также потребуется каким-то образом обновить пакет данных при возврате, в зависимости от того, используете ли вы только данные или также измените ихкак его использовать.

Любая из этих идей должна помочь вашему процессу.Это делает ваш код более читабельным и с меньшей вероятностью допустит какую-либо ошибку.

0 голосов
/ 03 февраля 2012

Если вы используете один из более поздних выпусков MATLAB, вам следует воспользоваться OOPS (объектно-ориентированной системой программирования).

Вы должны придерживаться принципов разработки программного обеспечения и начать с разработки надежного программного обеспечения,Вы должны сделать это перед написанием любого кода.Я рекомендую использовать UML для моделирования программного обеспечения.

...