How to remove data from a plot when box in checkbox is deselected

I have created a figure with 5 checkboxes and have created functions such that when each box is checked, the respective data is added to the plot
fig = figure; %creates checkbox with the currency selections
checkbox_USD = uicontrol(fig,'Style','Checkbox','String','USD','Position',[10 105 100 15],...
'Callback', @Selected_USD); %callback allows a function to operate when box is selected
checkbox_EUR = uicontrol(fig,'Style','Checkbox','String','EUR','Position',[10 85 100 15],...
'Callback', @Selected_EUR);
checkbox_AUD = uicontrol(fig,'Style','Checkbox','String','AUD','Position',[10 65 100 15],...
'Callback', @Selected_AUD);
checkbox_CAD = uicontrol(fig,'Style','Checkbox','String','CAD','Position',[10 45 100 15],...
'Callback', @Selected_CAD);
checkbox_HKD = uicontrol(fig,'Style','Checkbox','String','HKD','Position',[10 25 100 15],...
'Callback', @Selected_HKD);
function Selected_USD (h,~)%callback for 'USD' selection
checked_USD = get(h,'Value');
if checked_USD == 1
graph_function_USD
hold on
end
end
function Selected_EUR (h,~) %callback for 'EUR' selection
checked_EUR = get(h,'Value');
if checked_EUR == 1
graph_function_EUR
hold on
end
end
function Selected_AUD (h,~) %callback for 'AUD' selection
checked_AUD = get(h,'Value');
if checked_AUD == 1
graph_function_AUD
hold on
end
end
function Selected_CAD (h,~) %callback for 'CAD' selection
checked_CAD = get(h,'Value');
if checked_CAD == 1
graph_function_CAD
hold on
end
end
function Selected_HKD (h,~) %callback for 'HKD' selection
checked_HKD = get(h,'Value');
if checked_HKD == 1
graph_function_HKD
hold on
end
end
my question is as follows,
how do i make it so that when the box is deselected, the data is removed from the plot?
any help would be appreciated :)

 Accepted Answer

Edit: After getting the graph_function, removing the old suggestions for clarity.
% These two lines are most likely to change, put them at the top
currency_type = {'USD','EUR','AUD','CAD','HKD'}
source_file = {'exchange_ratesUSD.xlsx','each other name here'} % has to be completed
fig = figure('Name','Currency Data by Type');
ax = axes(fig);
% fig_height = fig.Position(4); see 'Position' of checkbox_obj
line_obj = gobjects(1,numel(currency_type));
checkbox_obj = gobjects(1,numel(currency_type));
for i = 1:numel(line_obj)
line_obj(i) = line(ax,nan,nan); % Where i == 1 corresponds to USD, etc. etc.
set(line_obj(i),'UserData',struct('type',currency_type{i},'source',source_file{i})); % Associate type with the line object
checkbox_obj(i) = uicontrol(fig,...
'Style','Checkbox',...
'String',currency_type{i},...
'Position',[10 105-20*i 100 15],... % could use fig_height here instead of 105
'Callback', {@Selected_Callback,line_obj(i)});
end
% note, want to remove "currency_type" here:
function Selected_Callback (h,~,line_obj)
checked = get(h,'Value');
graph_function(checked,line_obj);
end
And for the function referenced by the callback function:
function graph_function(checked,line_obj)
% GRAPH_FUNCTION Graph data depending if checkbox is ticked and which checkbox it is
currency_type = line_obj.UserData.type; % Retrieve the thing we associated with l(i)
if ~checked
set(line_obj,'XData',nan,'YData',nan); % "turn off the line"
% note that this can be done using set(line_obj,'Visible','off');
% however, if you have a lot of data points, then it can be faster just to do it this way.
else
data = readtable(line_obj.UserData.source);
x = table2array(data(:,1));
y = table2array(data(:,3));
set(line_obj,'XData',x,'YData',y);
end
end

11 Comments

thanks for the response :)
with the generalised graph function, would i just use a switch statement that refers to the currency_type selection?
my original graph function is below
function graph_function_USD
USD = readtable('exchange_ratesUSD.xlsx'); %loads excel file for USD exchange rates
USD.Date = datenum(USD{:,1}); %converts dates from string to serial date number
USD_array = table2array(USD); %converts table to matrix
plot(USD_array(:,1),USD_array(:,3)); %plots date against exchange rate
title('GBP/USD Exchange Rate');
xlabel('Date');
ylabel('Comparative Exchange Rate');
yearly_tick =datenum(1999:1:2019,1,1); %set ticks to occur in yearly intervals
set(gca,'xtick',yearly_tick);
datetick('x','mmm/yyyy','keepticks');
xtickangle(90); %rotate x-axis labels to prevent cluttering
set(gca,'XMinorTick','on');
set(gcf,'visible','on');
legend('USD')
end
and i've tried using a switch statement like this:
function graph_function
switch currency_type
case 1
USD = readtable('exchange_ratesUSD.xlsx'); %loads excel file for USD exchange rates
USD.Date = datenum(USD{:,1}); %converts dates from string to serial date number
USD_array = table2array(USD); %converts table to matrix
plot(USD_array(:,1),USD_array(:,3)); %plots date against exchange rate
title('GBP Exchange Rate');
xlabel('Date');
ylabel('Comparative Exchange Rate');
yearly_tick =datenum(1999:1:2019,1,1); %set ticks to occur in yearly intervals
set(gca,'xtick',yearly_tick);
datetick('x','mmm/yyyy','keepticks');
xtickangle(90); %rotate x-axis labels to prevent cluttering
set(gca,'XMinorTick','on');
set(gcf,'visible','on');
legend('USD')
% case 2 etc...
is that correct?
Also what is the purpose of this line?
graph_function(checked,currency_type,line_obj);
OK so if you just have a list of xlsx files you want to read from for each different checkbox, then I would use those as your 'UserData' as follows:
% These two lines are most likely to change, put them at the top
currency_type = {'USD','EUR','AUD','CAD','HKD'}
source_file = {'exchange_ratesUSD.xlsx','each other name here'} % has to be completed
fig = figure('Name','Currency Data by Type');
ax = axes(fig);
% fig_height = fig.Position(4); see 'Position' of checkbox_obj
line_obj = gobjects(1,numel(currency_type));
checkbox_obj = gobjects(1,numel(currency_type));
for i = 1:numel(line_obj)
line_obj(i) = line(ax,nan,nan); % Where i == 1 corresponds to USD, etc. etc.
set(line_obj(i),'UserData',struct('type',currency_type{i},'source',source_file{i})); % Associate type with the line object
checkbox_obj(i) = uicontrol(fig,...
'Style','Checkbox',...
'String',currency_type{i},...
'Position',[10 105-20*i 100 15],... % could use fig_height here instead of 105
'Callback', {@Selected_Callback,l(i)});
end
% note, want to remove "currency_type" here:
function Selected_Callback (h,~,line_obj)
checked = get(h,'Value');
graph_function(checked,line_obj);
end
And in the callback function:
function graph_function(checked,line_obj)
% GRAPH_FUNCTION Graph data depending if checkbox is ticked and which checkbox it is
currency_type = line_obj.UserData.type; % Retrieve the thing we associated with l(i)
if ~checked
set(line_obj,'XData',nan,'YData',nan); % "turn off the line"
% note that this can be done using set(line_obj,'Visible','off');
% however, if you have a lot of data points, then it can be faster just to do it this way.
else
data = readtable(line_obj.UserData.source);
x = table2array(data(:,1));
y = table2array(data(:,3));
set(line_obj,'XData',x,'YData',y);
end
end
I'm getting an error:
Error using checkbox_test3>Selected_Callback
Too many input arguments.
Error while evaluating UIControl Callback.
Check on line 17:
'Callback', {@Selected_Callback,l(i)});
Should be changed to
'Callback', {@Selected_Callback,line_obj(i)});
Sorry about that.
Also at the top, if you're running this as a script you may want to call clear at the beginning if you don't need to keep things in workspace memory.
Error using checkbox_test3>Selected_Callback
Too many input arguments.
Error while evaluating UIControl Callback.
This means that you created a checkbox uicontrol called checkbox_test3. You assigned its Callback property the function handle Selected_Callback. When you assign a callback function handle to a Matlab uicontrol such as a checkbox, the checkbox automatically gets two other input arguments first: source which is the h from your original Selected_Callback and it references the uicontrol object itself, and event, which is an "EventData" object that has a few fields with different information depending on the type of uicontrol, the type of interaction (e.g. Callback or SelectionChangedFcn, etc) and that is all dependent upon the type of event that is issued during the interaction. My guess is that your new Selected_Callback function doesn't account for both of these automatically-added inputs. If you don't use one or both of them, then you can set the corresponding argument to Selected_Callback as ~. You can also specify that you do not want to use them during the assignment of the Callback property, for example by setting
checkbox_test3.Callback = @(source,~,line_obj)Selected_Callback(line_obj(i));
Now when i try run the code i end up with this
>> checkbox_test3.Callback = @(source,~,line_obj)Selected_Callback(line_obj(i));
>> checkbox_test3
checkbox_test3 =
struct with fields:
Callback: @(source,~,line_obj)Selected_Callback(line_obj(i))
sorry I'm not entirely sure i've done it correctly i am fairly new to MATLAB
No problem. Wherever you are making checkbox_test3, you will want to initialize it first, before assigning the Callback. If you start out by assigning the property before the object exists, then Matlab will just interpret checkbox_test3 as a struct with the field Callback, as opposed to a graphics object.
You can initialize the object with the Callback that you want by assigning the property during construction of the object, such as:
checkbox_test3 = uicontrol(fig,...
'Style','Checkbox',...
'String',currency_type{3},...
'Position',[10 105-20*3 100 15],... % could use fig_height here instead of 105
'Callback', {@Selected_Callback,line_obj(3)});
Notice that in this example I am using the "hard-coded" index 3 where I had been using i in the loop previously. For this object to be created successfully, you will need to have a cell array currency_type, whose third element ( currency_type{3} ) corresponds to the char array you want. line_obj(3) should correspond to some line object, so it doesn't have to be from an array it could be whatever line you have initialized previously.
so would i have to manually create the cell array containing the different currency types?
Also when i try to use that checkbox code it say's
unable to define variable 'checkbox_test3' because it has the same name as the script
I'd suggest naming the script something else, such as currencyType_checkboxTest or something that fits your name convention.
Yes, the cell arrays currency_type and source_file in the code from the top-level comment would need to be manually defined by you. Each element of source_file should match the corresponding element of currency_type.
source_file should be the names of the xlsx source files. You can also parse their names dynamically if you have them all in one folder by calling the dir command on that folder, but I think you just want to get the test example working so I wouldn't worry about that for now.
What should the currency array look like?

Sign in to comment.

More Answers (0)

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Products

Release

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!