Plotting on GUI and navigate between the figures

Hello everyone,
So, I want to plot some graphs in my GUI, but using the same axes object. And then, I'll have two buttons to navigate between the figures. Something like what is shown in the fig below.
graphs.PNG
Any ideas on how to do this?
I tried creating a sequence with all the graphs that will be created, and assign a signal to the two buttons of the fig. above (-1 and 1).
function manageGraphs(handles, hObject, sinal)
% Define the sequences of graphs, for each topology
sequence = {'perdas_ripple', 'volume_ripple', ...
'perdas_fsw','volume_fsw', ...
'pareto_ripple', 'pareto_fsw'};
dim_sequence = length(sequence);
start_graphs = 1;
end_graphs = 6;
% Get the current index_sequence from handles
index_sequence = 4;
fsw = handles.fsw;
delta_i = handles.delta_i;
if (sinal == -1)
% If the user pressed the left button, i.e., sinal = -1
if(index_sequence ~= start_graphs)
% If the user did not reach the first element
% index_sequence ~= start_current_graphs
% Sweep to the previous graph, if the user did not reach the
% beginning of the list
index_sequence = index_sequence + sinal;
else
% index_sequence == start_losses_graphs
% If the user reaches the start, returns to the end
index_sequence = end_graphs;
end
% If the sequence ends, return to the start
elseif sinal == 1
% If the user pressed the right button, i.e., sinal = 1
if(index_sequence ~= end_graphs)
index_sequence = index_sequence + sinal;
else
% If the user reached the last element in the sequence of graphs
% of losses, returns to the start of this list
index_sequence = start_graphs;
end
end
seq = sequence{index_sequence};
% Make 'grafico_corrente' the current graph
axes(handles.graphs);
% Plot the graphs
switch seq
case 'perdas_ripple'
plot(handles.x_ripple, handles.PerdasT_ripple); hold on;
plot(handles.x_ripple, handles.PerdasL_ripple); hold on;
plot(handles.x_ripple, handles.PerdasTotais_ripple);
xlabel('Ripple de Corrente');
ylabel('Perdas [W]');
title('Perdas nos Transistores, Indutores e Totais');
legend('Perdas nos Transistores', 'Perdas nos Indutores', 'Perdas Totais');
case 'volume_ripple'
plot(handles.x_ripple, handles.VolL_ripple); hold on;
plot(handles.x_ripple, handles.VolHS_ripple); hold on;
plot(handles.x_ripple, handles.VolumeTotal_ripple);
xlabel('Ripple de Corrente');
ylabel('Volume [dm³]'); % Verificar se é dm³ msm
title('Volume dos Indutores, Dissipadores e Total');
legend('Volume dos Indutores', 'Volume dos Dissipadores', 'Volume Total');
case 'perdas_fsw'
plot(handles.x_fsw, handles.PerdasT_fsw); hold on;
plot(handles.x_fsw, handles.PerdasL_fsw); hold on;
plot(handles.x_fsw, handles.PerdasTotais_fsw);
xlabel('Frequência de Chaveamento');
ylabel('Perdas [W]');
title('Perdas nos Transistores, Indutores e Totais');
legend('Perdas nos Transistores', 'Perdas nos Indutores', 'Perdas Totais');
case 'volume_fsw'
plot(handles.x_fsw, handles.VolL_fsw); hold on;
plot(handles.x_fsw, handles.VolHS_fsw); hold on;
plot(handles.x_fsw, handles.VolumeTotal_fsw);
xlabel('Frequência de Chaveamento');
ylabel('Volume [dm³]'); % Verificar se é dm³ msm
title('Volume dos Indutores, Dissipadores e Total');
legend('Volume dos Indutores', 'Volume dos Dissipadores', 'Volume Total');
case 'pareto_ripple'
for k = 1 : length(delta_i)
plot(handles.DenPot(k,1:end), handles.Rend(k,1:end)); hold on;
legend("Ripple = " + delta_i(k));
end
xlabel('Densidade de Potência [kW/dm³]');
ylabel('Rendimento');
title('Rendimento x Densidade de Potência - Diferentes Ripples');
case 'pareto_fsw'
for k = 1 : length(fsw)
plot(handles.DenPot(:,k), handles.Rend(:,k)); hold on;
legend("Fsw = " + fsw(k) + "kHz");
end
xlabel('Densidade de Potência [kW/dm³]');
ylabel('Rendimento');
title('Rendimento x Densidade de Potência - Diferentes Fsw');
end
end
obs.: Is it correct how I made the plot loops and the legends of the two last cases (pareto_ripple and pareto_fsw) ?
Thanks in advance!

7 Comments

The approach you seem to be taking is to toggle through a list of data sets and destroy & produce a plot on each button click. Each button click pulls the data from your GUI and produces a new figure within the existing axes.
What if, instead, you had all 6 axes on top of eachother and in each axes, the data are always plotted and up to date. The axes are updated every time a GUI component is changed. Then, instead of producing the plot when the buttons are pressed, you merely set the current axes visibility to 'off' and the next axes visibility of 'on'.
That proposal will still require some time to produce all of the plots but only one of them will be visible at a time and the toggle action will be much faster.
Thanks for your answer.
So, how do I do this?
I put all the axes on the GUI and set their visibility to off, initially. When I press the button to run the main function, I plot the result on the first axes. As shown in the code below. The problem is doing it like that all the graphs are plotted, the axis become a mess as does the title.
Other thing, how do I know which one is the active axes the moments I press the 'go back' or 'go forward' button?
% --- Executes on button press in simular_projeto.
function simular_projeto_Callback(hObject, eventdata, handles)
% hObject handle to simular_projeto (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
try
projeto(hObject, handles);
handles = guidata(hObject);
guidata(hObject, handles);
fsw = handles.fsw;
delta_i = handles.delta_i;
set(handles.graph_1, 'Visible', 'on');
set(handles.graph_2, 'Visible', 'off');
set(handles.graph_3, 'Visible', 'off');
set(handles.graph_4, 'Visible', 'off');
set(handles.graph_5, 'Visible', 'off');
set(handles.graph_6, 'Visible', 'off');
% guard against plotHandle not being set
if ~isempty(handles.graph_1)
axes(handles.graph_1);
hold on;
plot(handles.x_ripple, handles.PerdasT_ripple);
plot(handles.x_ripple, handles.PerdasL_ripple);
plot(handles.x_ripple, handles.PerdasTotais_ripple);
hold off;
xlabel('Ripple de Corrente');
ylabel('Perdas [W]');
title('Perdas nos Transistores, Indutores e Totais');
legend('Perdas nos Transistores', 'Perdas nos Indutores', 'Perdas Totais');
end
if ~isempty(handles.graph_2)
axes(handles.graph_2);
hold on;
plot(handles.x_ripple, handles.VolL_ripple);
plot(handles.x_ripple, handles.VolHS_ripple);
plot(handles.x_ripple, handles.VolumeTotal_ripple);
hold off;
xlabel('Ripple de Corrente');
ylabel('Volume [dm³]'); % Verificar se é dm³ msm
title('Volume dos Indutores, Dissipadores e Total');
legend('Volume dos Indutores', 'Volume dos Dissipadores', 'Volume Total');
end
if ~isempty(handles.graph_3)
axes(handles.graph_3);
hold on;
plot(handles.x_fsw, handles.PerdasT_fsw);
plot(handles.x_fsw, handles.PerdasL_fsw);
plot(handles.x_fsw, handles.PerdasTotais_fsw);
hold off;
xlabel('Frequência de Chaveamento');
ylabel('Perdas [W]');
title('Perdas nos Transistores, Indutores e Totais');
legend('Perdas nos Transistores', 'Perdas nos Indutores', 'Perdas Totais');
end
if ~isempty(handles.graph_4)
axes(handles.graph_4);
hold on;
plot(handles.x_fsw, handles.VolL_fsw);
plot(handles.x_fsw, handles.VolHS_fsw);
plot(handles.x_fsw, handles.VolumeTotal_fsw);
hold off;
xlabel('Frequência de Chaveamento');
ylabel('Volume [dm³]'); % Verificar se é dm³ msm
title('Volume dos Indutores, Dissipadores e Total');
legend('Volume dos Indutores', 'Volume dos Dissipadores', 'Volume Total');
end
if ~isempty(handles.graph_5)
axes(handles.graph_5);
hold on;
for k = 1 : length(delta_i)
txt = ['Ripple = ',num2str(delta_i(k))];
plot(handles.DenPot(k,1:end), handles.Rend(k,1:end), 'DisplayName',txt);
% legend("Ripple = " + delta_i(k));
end
hold off;
legend show
xlabel('Densidade de Potência [kW/dm³]');
ylabel('Rendimento');
title('Rendimento x Densidade de Potência - Diferentes Ripples');
end
if ~isempty(handles.graph_6)
axes(handles.graph_6);
hold on;
for k = 1 : length(fsw)
txt = ['Fsw = ',num2str(fsw(k)/1000), 'kHz'];
plot(handles.DenPot(:,k), handles.Rend(:,k), 'DisplayName',txt);
% legend("Fsw = " + fsw(k) + "kHz");
end
hold off;
legend show
xlabel('Densidade de Potência [kW/dm³]');
ylabel('Rendimento');
title('Rendimento x Densidade de Potência - Diferentes Fsw');
end
catch ME
% Some error happened if you get here.
callStackString = GetCallStack(ME);
errorMessage = sprintf('Error in program %s.\nTraceback (most recent at top):\n%s\nError Message:\n%s', ...
mfilename, callStackString, ME.message);
WarnUser(errorMessage);
end
"I put all the axes on the GUI and set their visibility to off, initially. "
It might make more sense to leave one of the axes visible; whichever axes is the default, initial axes.
"When I press the button to run the main function, I plot the result on the first axes."
That approach is fine but my recommendation was to produce all of the plots ahead of time so that when you toggle through the axes, the date merely appears rather than being re-drawn every time. That will likely require some restructuring of your code.
"As shown in the code below. The problem is doing it like that all the graphs are plotted, the axis become a mess as does the title."
I haven't looked too deeply into your code but it appears that you're not using axis handles as inputs to the plot(), title() etc. It's generally good practice to always specify the axis handle.
plot(axisHandle, x, y);
title(axisHandle, 'myTitle')
Note that this problem will alos be solved by producing the plots ahead of time. The point of my suggestion is that toggling through the axes merely makes them visible/invisible and there is no need to do any plotting when toggling through the axes.
"Other thing, how do I know which one is the active axes the moments I press the 'go back' or 'go forward' button? "
Presumably you have a list of axes such as
handles.ax1
handles.ax2
handles.ax3
To see which one is visible, look at their Visible property or you could keep track of how many times the << and >> buttons were pressed.
Ok, I get it now. So I tried to plot all the graphs on their respective axes using the axis handles on the plot() (just like the code below), but all the curves are being plotted on top of each other.
if ~isempty(handles.graph_1)
axes(handles.graph_1);
hold on;
plot(handles.graph_1, handles.x_ripple, handles.PerdasT_ripple);
plot(handles.graph_1, handles.x_ripple, handles.PerdasL_ripple);
plot(handles.graph_1, handles.x_ripple, handles.PerdasTotais_ripple);
hold off;
xlabel(handles.graph_1, 'Ripple de Corrente');
ylabel(handles.graph_1, 'Perdas [W]');
title(handles.graph_1, 'Perdas nos Transistores, Indutores e Totais');
legend(handles.graph_1, 'Perdas nos Transistores', 'Perdas nos Indutores', 'Perdas Totais');
end
if ~isempty(handles.graph_2)
axes(handles.graph_2);
set(handles.graph_2, 'Visible', 'off');
hold on;
plot(handles.graph_2, handles.x_ripple, handles.VolL_ripple);
plot(handles.graph_2, handles.x_ripple, handles.VolHS_ripple);
plot(handles.graph_2, handles.x_ripple, handles.VolumeTotal_ripple);
hold off;
xlabel(handles.graph_2, 'Ripple de Corrente');
ylabel(handles.graph_2, 'Volume [dm³]'); % Verificar se é dm³ msm
title(handles.graph_2, 'Volume dos Indutores, Dissipadores e Total');
legend(handles.graph_2, 'Volume dos Indutores', 'Volume dos Dissipadores', 'Volume Total');
end
if ~isempty(handles.graph_3)
axes(handles.graph_3);
set(handles.graph_3, 'Visible', 'off');
hold on;
plot(handles.graph_3, handles.x_fsw, handles.PerdasT_fsw);
plot(handles.graph_3, handles.x_fsw, handles.PerdasL_fsw);
plot(handles.graph_3, handles.x_fsw, handles.PerdasTotais_fsw);
hold off;
xlabel(handles.graph_3, 'Frequência de Chaveamento');
ylabel(handles.graph_3, 'Perdas [W]');
title(handles.graph_3, 'Perdas nos Transistores, Indutores e Totais');
legend(handles.graph_3, 'Perdas nos Transistores', 'Perdas nos Indutores', 'Perdas Totais');
end
if ~isempty(handles.graph_4)
axes(handles.graph_4);
set(handles.graph_4, 'Visible', 'off');
hold on;
plot(handles.graph_4, handles.x_fsw, handles.VolL_fsw);
plot(handles.graph_4, handles.x_fsw, handles.VolHS_fsw);
plot(handles.graph_4, handles.x_fsw, handles.VolumeTotal_fsw);
hold off;
xlabel(handles.graph_4, 'Frequência de Chaveamento');
ylabel(handles.graph_4, 'Volume [dm³]'); % Verificar se é dm³ msm
title(handles.graph_4, 'Volume dos Indutores, Dissipadores e Total');
legend(handles.graph_4, 'Volume dos Indutores', 'Volume dos Dissipadores', 'Volume Total');
end
if ~isempty(handles.graph_5)
axes(handles.graph_5);
set(handles.graph_5, 'Visible', 'off');
hold on;
for k = 1 : length(delta_i)
txt = ['Ripple = ',num2str(delta_i(k))];
plot(handles.graph_5, handles.DenPot(k,1:end), handles.Rend(k,1:end), 'DisplayName',txt);
% legend("Ripple = " + delta_i(k));
end
hold off;
legend show
xlabel(handles.graph_5, 'Densidade de Potência [kW/dm³]');
ylabel(handles.graph_5, 'Rendimento');
title(handles.graph_5, 'Rendimento x Densidade de Potência - Diferentes Ripples');
end
if ~isempty(handles.graph_6)
axes(handles.graph_6);
set(handles.graph_6, 'Visible', 'off');
hold on;
for k = 1 : length(fsw)
txt = ['Fsw = ',num2str(fsw(k)/1000), 'kHz'];
plot(handles.graph_6, handles.DenPot(:,k), handles.Rend(:,k), 'DisplayName',txt);
% legend("Fsw = " + fsw(k) + "kHz");
end
hold off;
legend show
xlabel(handles.graph_6, 'Densidade de Potência [kW/dm³]');
ylabel(handles.graph_6, 'Rendimento');
title(handles.graph_6, 'Rendimento x Densidade de Potência - Diferentes Fsw');
end
Ahhh.... sorry. I forgot that axis off only turns off the axes and does not turn off the content of the axes.
The small fix is to apply the visibility toggle to axis children, too.
set(handles.graph_1, 'Visible', 'off');
set(handles.graph_1.Children, 'Visible', 'off');
Hey man, I'm sorry but I still can't get this right. Do I put this line of code for every axes?
set(handles.graph_1.Children, 'Visible', 'off');
Even though I'm setting axes(AxesHandle) and plot(AxesHandle, x, y) and setting all of the others axes to not visible (even their children as you pointed), all the plots are going to the same graph and are shown at the same time.
graphs.PNG
Every time you want to turn an axes on or off you must execute both lines of code.
set(handles.graph_1, 'Visible', 'off'); % or 'on'
set(handles.graph_1.Children, 'Visible', 'off'); % or 'on'

Sign in to comment.

 Accepted Answer

Summary of the comments under the question:
Instead of using the [<<] and [>>] buttons to toggle through various data sets that will be plotted on the axes, you can create a number of axes that each host a dataset while the toggle buttons control which axes are visible.
Here are the steps needed and an example of the code for each step.
  1. Plot each set of data to it's corresponding axes
  2. Set the visibility of the axes and its children to "off" except for one of the axes.
  3. The callback functions to the toggle buttons will merely cycle through the list of axes.
% Step 1
hold(handles.axes1,'on')
plot(handles.axes1, x1, y1)
plot(handles.axes1, w1, z1)
hold(handles.axes2,'on')
plot(handles.axes2, x2, y2)
plot(handles.axes2, w2, z2)
hold(handles.axes3,'on')
plot(handles.axes3, x3, y3)
plot(handles.axes3, w3, z3)
% Step 2
handles.axes1.Visible = 'on'; % this one is visible
set(handles.axes1.Children, 'Visible','on')
% put this axis on top
uistack(handles.axes1,'top')
handles.axes2.Visible = 'off';
set(handles.axes2.Children, 'Visible','off')
handles.axes3.Visible = 'off';
set(handles.axes3.Children, 'Visible','off')
% Step 3
% There are lots of ways to do this; here's 1 example.
% **********************************************************
% In the Startup function store the axis label and axis
% index in the handles structure. Add the first two lines
% prior to the 3rd line which should alread exist in your
% GUI opening function.
handles.allAxes = [handles.axes1, handles.axes2, handles.axes3];
handles.axisNumber = 1:numel(handles.allAxes);
guidata(hObject, handles); % THIS LINE SHOULD ALREADY EXIST
% **********************************************************
function toggleButtonLeft(hobj, event, handles)
% Since this is the left toggle button,
% we'll cycle circularly to the left
handles.axisNumber = circshift(handles.axisNumber, 1); % circshift(..., -1) for right-button
% update stored data
guidata(hObject, handles);
% turn on current axes & children
handles.allAxes(handles.axisNumber(1)).Visible = 'on';
set(handles.allAxes (handles.axisNumber(1)).Children,'Visible','on')
% turn off all other axes and children
for j = 2:numel(handles.axisNumber)
handles.allAxes (handles.axisNumber(j)).Visible = 'off';
set(handles.allAxes (handles.axisNumber(j)).Children,'Visible','off')
end
% put current axis on top
uistack(handles.allAxes(handles.axisNumber(1)),'top')
end

10 Comments

Thanks man! It works, just three more question:
The legend of all the plots keeps showing in the first one (but their color is greyish). How do I take them off?
How do I make the left and right buttons commuticate between each other? That means, if I press a left and a right I want to end up in the same place. This isn't happening right now.
How can I make sure that when the user press the simulation again, withou closing the GUI, all the plots are erased?
"Thanks man! It works"
Great!
"The legend of all the plots keeps showing in the first one (but their color is greyish). How do I take them off?"
The legend doesn't appear when I run that code. Have you added anything?
Do you want to remove the legend completely (having trouble understanding 'take them off')?
"How do I make the left and right buttons commuticate between each other? That means, if I press a left and a right I want to end up in the same place. This isn't happening right now."
Good point. I'll update the code in step 3; check back in a few minutes.
"How can I make sure that when the user press the simulation again, withou closing the GUI, all the plots are erased?"
At the top of the callback function that controls the simulation, clear the axes using cla(ax)
allAxes = [handles.axes1, handles.axes2, handles.axes3];
arrayfun(@(i)cla(allAxes(i)),1:numel(allAxes))
"The legend doesn't appear when I run that code. Have you added anything?"
Yes, I added the legend, labels and titles just after the plot() function. I want that each plot has its own title, axis labels and legend.
Sorry, I was confusing this question with another one. I see what you mean now regarding the lengend.
As I metioned before, you'll need to specify the axis handle on all graphics functions.
legend(handles.axis1, . . .)
title(handles.axis1, . . .)
xlabel(handles.axis1, . . .)
% etc....
% **********************************************************
% In the Startup function or within the initial plotting
% function, store the axis label and axis index in the
% GUI figure handle.
data.allAxes = [handles.axes1, handles.axes2, handles.axes3];
data.axisNumber = 1:numel(data.allAxes);
guidata(handles.figure,data) % 1st input is the GUI figure handle
% **********************************************************
What is the handle figure?
legend(handles.axis1, . . .)
title(handles.axis1, . . .)
xlabel(handles.axis1, . . .)
Yes that's what I did after each plot(), but the problem persists.
And thank you again!
"What is the handle figure? "
As the comment next to that line explains, you need to enter the handle to your GUI figure as the first input. I don't know what your handle looks like to I just used handle.figure.
"Yes that's what I did after each plot(), but the problem persists."
When you turn the visibility of the axes on/off, that should also toggle the visibility of the title and axis labels but it doesn't toggle the visibility of the legend since the legend is a child of the figure, not the axes.
The simplest way to take care of that is by adding this line to the code that puts the current axes on "top" which will hide the other legends.
% put current axis on top
uistack(data.allAxes(data.axisNumber(1)),'top')
Hey man,
If I do this in the OpeningFcn:
% **********************************************************
% In the Startup function or within the initial plotting
% function, store the axis label and axis index in the
% GUI figure handle.
data.allAxes = [handles.graph_1, handles.graph_2, handles.graph_3, handles.graph_4, handles.graph_5, handles.graph_6];
data.axisNumber = 1:numel(data.allAxes);
guidata(handles.figMainWindow,data) % 1st input is the GUI figure handle
% **********************************************************
And then in my function I do this:
% Get stored axes list and axis number
data = guidata(hObject);
% Clear all the graphs
arrayfun(@(i)cla(data.allAxes(i)),1:numel(data.allAxes))
Why do I get this error, if I defined allAxes in the OpeningFcn?
Error Message:
Reference to non-existent field 'allAxes'.
Pedro Augusto de Castro e Castro, sorry about that. I've updated the code in my new answer with a new approach. Be sure to look at all of the code in my answer carefully for changes.
High five! Good teamwork.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!