MATLAB: экспортировать данные из флажков, созданных циклом для кнопки

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

Во-первых, я создал (с помощью «il_raffa») несколько флажков, которые должны быть гибкими (ii: ввод цикла для), которые из моего кода в принципе можно обобщить примерно так:

Окно графического интерфейса

N=500;
M=300;

handles.fig=figure('Units', 'Pixels','Position',[100 100 N M]);

handles.axes=axes('Units', 'Pixels','tag','axes_tag','Position',[25 25 N-200     M-50]);

for ii=1:4; %input exemple

   handles.check{ii}=uicontrol('style','checkbox','string', ...
      ['Display_file_' num2str(ii)],'tag',['c_b_' num2str(ii)], ...
      'position',[N-150 M/2-ii*20 100 25],'callback','plot_sel_cb(handles.axes)');
end

обратный вызов флажка

function plot_sel_cb(ax_h)
cb_id=get(gcbo,'string')
cb_pos=get(gcbo,'position')
val=get(gcbo,'value')
path=get(gcbo,'userdata');
axes(ax_h)
hold on

if val

   x=1:10;
   y=[1:10].*cb_pos(2)/100;
   plot(x,y,'color,[rand(1) rand(1) rand(1)])
   legend(cb_id)

    set(h,'tag',cb_id)


else 
    delete(findobj('tag',cb_id))
end

Из этого кода я хотел бы создать кнопку, которая берет только [x, y] из отмеченных флажков, чтобы создать, например, переменную со всеми этими данными внутри.

Вторая проблема заключается в том, что мне не удалось создать легенду для «графика (x, y, 'цвет, [rand (1) rand (1) rand (1)])», которая добавляет имя «cb_id», когда установлен флажок, соответствующий данным.

ПОМОЩЬ

Спасибо


person Tual Monfort    schedule 23.10.2015    source источник


Ответы (1)


Позвольте мне начать со второй проблемы: добавьте легенду.

В checkbox callback вы добавляете/удаляете строки в соответствии с status (отмечено/не отмечено) флажка.

Добавить элемент в легенду довольно просто, вам просто нужно вставить нужную строку (в вашем случае cb_id) в cellarray и установить ее в качестве входного параметра для функции legend.

Удалить элемент из легенды, когда вы снимаете флажок, оставляя другой, может быть немного сложнее.

Учитывая, что у вас, похоже, не так много линий для построения, самым простым (даже если не «оптимальным») подходом может быть изменение способа работы checkbox callbak.

Юо может закодировать его так, чтобы каждый раз, когда он вызывается, он:

  • удалить все ранее нанесенные линии
  • удалить текущую легенду
  • построить (в цикле) все строки в соответствии со статусом флажка
  • создать правильную легенду

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

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

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

Например, в основной функции у вас есть ii флажков; с помощью следующего кода вы можете назначить количество флажков и их дескрипторов:

figure_data.n_cb=ii;
figure_data.cb_handles=handles.check;
set(handles.fig,'userdata',figure_data)

Я использовал этот подход во всех функциях, которые вы можете найти ниже.

Что касается первой проблемы: pushbutton для извлечения значений (x, y).

Вы можете добавить pushbutton uicontrol в основную функцию (согласно флажкам).

pushbutton это:

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

Есть несколько способов получить значения (x,y), два из них: - вы можете присвоить их переменной в обратном вызове флажка (в этом случае вам фактически не нужна кнопка) - вы можете использовать тот факт, что данные каждой линии, нанесенной на оси, также хранятся в свойствах xdata и ydata в дескрипторе графика.

Из axes uicontrol вы можете получить к ним доступ через свойство children: оно возвращает дескрипторы каждого элемента, нанесенного на оси, поэтому вы можете написать цикл, проходящий по этим дескрипторам и получить данные.

Поскольку, в принципе, ваши данные могут иметь разный размер (график, связанный с флажком_1, может иметь больше данных, чем график с флажком_2), вы не должны использовать матрицу для хранения всех из них.

Было бы лучше использовать cellarray или массив struct

Далее вы можете найти обновленную версию основной функции, в которой добавлены pushbuton ha и pushbutton callback.

Основная функция графического интерфейса

N=500;
M=300;
% Added ",'toolbar','figure'" to show the figure toolbar (zoom, rotate,
% ...)
handles.fig=figure('Units', 'Pixels','Position',[100 100 N M],'toolbar','figure');


handles.axes=axes('Units', 'Pixels','tag','axes_tag','Position',[25 25 N-200 M-50]);

for ii=1:4; %input exemple

% Changed definition of "handles.check" from "cellarray" to "array"
% Added setting of each checkbox "userdata" to the value of loop index (a
% way to automatically identify the checkboxes)
%
%    handles.check{ii}=uicontrol('style','checkbox','string', ...
   handles.check(ii)=uicontrol('style','checkbox','string', ...
      ['Display_file_' num2str(ii)],'tag',['c_b_' num2str(ii)], ...
      'position',[N-150 M/2-ii*20 100 25],'userdata',ii, ...
      'callback','plot_sel_cb(handles.axes)');

end
% Add the pushbutton (it is disabled at creation), it will be enabled by
% the checkbox callback if any checkbox set
handles.button=uicontrol('style','pushbutton','string','Export data', ...
   'enable','off','position',[N-150 M/2+50 100 25], ...
   'callback','export_data');
%
% Store info into figure "userdata"
%    number of checkboxes
%    status of the checkboxes (all unchecked at the beginning)
%    pushbuton handle
figure_data.n_cb=ii;
figure_data.selected_cb=zeros(1,ii);
figure_data.cb_handles=handles.check;
figure_data.button=handles.button;
%
set(handles.fig,'userdata',figure_data)

Обновлено checkbox callback

function plot_sel_cb(ax_h)
% Get the checkbox id
cb_id=get(gcbo,'userdata');
% Check if current checkbox has been checked (val=1) or unchecked (val=0)
val=get(gcbo,'value');
% Get the number of checkbox in the GUI
figure_data=get(gcf,'userdata');
n_cb=figure_data.n_cb;
cb_handles=figure_data.cb_handles;

% path=get(gcbo,'userdata');
axes(ax_h);

% Clear axes (delete plot) and delete the legend
p_h=get(gca,'children');
if(~isempty(p_h))
   delete(p_h);
   delete(figure_data.leg_h)
end

hold on

% Update current checkbox status in the checkbox info
figure_data.selected_cb(cb_id)=val;
% Initialize legend string, counter and plot handles array
legend_str={};
cnt=0;
p_h=[];
% Loop throught the checkbox to plot
for i=1:n_cb
   if(figure_data.selected_cb(i))
      cnt=cnt+1;
      x=1:10;
      % Get checkbox position (to generate exmple data to plot)
      cb_pos=get(cb_handles(i),'position');
      % Get checkbox id
      curr_cb=get(cb_handles(i),'userdata');
      y=[1:10].*cb_pos(2)/100;
      % Plot and store plot handle
      p_h(cnt)=plot(x,y,'color',[rand(1) rand(1) rand(1)],'linewidth',2);
      % Set the plot tag to the index of the checkbox (it will be used in
      % the pushbutton callback as index of the cellarray in which to store
      % the data plottd
      set(p_h(cnt),'userdata',curr_cb)
      % Get the string of the current chceckbox
      cb_string=get(cb_handles(i),'string');
      % Replace "_" with "_-" for the correct visualization
      cb_string=strrep(cb_string,'_','_-');
      % Build the legend's string
      legend_str{cnt}=cb_string;
   end
end
% Add the updated legend and store its handle in figure_data
if(~isempty(legend_str))
   figure_data.leg_h=legend(p_h,legend_str);
end
% Manage "Export data" pushbutton enabling
if(any(figure_data.selected_cb))
   set(figure_data.button,'enable','on')
else
   set(figure_data.button,'enable','off')
end
% Update figure data
set(gcf,'userdata',figure_data);

Обратный вызов с помощью кнопки

function export_data
% Get plotted data and set store them into a variable
%    the vaaible can be either a "cellarray" or an array of "struct"
% The data of each line plotted are stored in the "xdata" and "ydata"
% property of each "children" of the axis
p_h=get(gca,'children');
n_plot=length(p_h);
% Loop through the children to retreive the data
for i=1:n_plot
   cb_id=get(p_h(i),'userdata');
   x_data=get(p_h(i),'xdata');
   y_data=get(p_h(i),'ydata');
   % Create the cellarray "exported_data_cell_array"
   exported_data_cell_array{cb_id}=[x_data;y_data];
   % Create the struct "exported_data_struct"
   exported_data_struct(cb_id).checkbox_id=cb_id;
   exported_data_struct(cb_id).x_data=y_data;
   exported_data_struct(cb_id).y_data=y_data;
end
% Store the extractged data into th e figure_data
figure_data=get(gcf,'userdata');
figure_data.exported_data_cell_array=exported_data_cell_array;
figure_data.exported_data_struct=exported_data_struct;
set(gcf,'userdata',figure_data);

введите здесь описание изображения

Надеюсь это поможет.

person il_raffa    schedule 24.10.2015
comment
Еще раз спасибо il_raffa! Я все еще медленно просматриваю код, но он хорошо работает с тем, что я хотел сделать;). - person Tual Monfort; 26.10.2015
comment
Пожалуйста! Если вам нужна дополнительная информация или объяснение, пожалуйста, дайте мне знать. - person il_raffa; 26.10.2015