0
votes

I would need some help regarding a simple GUI I am working on.

I have a GUI with two plots : Pressure and Temperature and 3 sets of data each one containing one pressure curve and one temperature curve. I have on top of that, 3 checkbox that enable me to select the set of data I want to plot.

My question now is : I want the legend to be automatically updated regarding the set of data I have selected using the checkbox. That's mean adding new legend if a checkbox is selected on top of existing one but also removing the legend when checkbox is unselected.

Currently this is what I have as code when the GUI is opening:

function GUI_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to GUI (see VARARGIN)

handles.Data=load('DataCell');
cc=Lines(3);

hold(handles.PressureGraph);
grid(handles.PressureGraph,'on')
xlabel(handles.PressureGraph,'Time [s]')
ylabel(handles.PressureGraph,'Pressure [bars]')

handles.p1=plot(handles.PressureGraph,handles.Data.DataCell(:,1),handles.Data.DataCell(:,2),'color',cc(1,:),'DisplayName','1');
set(handles.p1, 'Visible', 'off');

handles.p2=plot(handles.PressureGraph,handles.Data.DataCell(:,4),handles.Data.DataCell(:,5),'color',cc(2,:),'DisplayName','2');
set(handles.p2, 'Visible', 'off');

handles.p3=plot(handles.PressureGraph,handles.Data.DataCell(:,7),handles.Data.DataCell(:,8),'color',cc(3,:),'DisplayName','3');
set(handles.p3, 'Visible', 'off');


hold(handles.TempGraph);
grid(handles.TempGraph,'on')
xlabel(handles.TempGraph,'Time [s]')
ylabel(handles.TempGraph,strcat('Temperature [',char(176),']'))

handles.t1=plot(handles.TempGraph,handles.Data.DataCell(:,1),handles.Data.DataCell(:,3),'color',cc(1,:),'DisplayName','1');
set(handles.t1, 'Visible', 'off');

handles.t2=plot(handles.TempGraph,handles.Data.DataCell(:,4),handles.Data.DataCell(:,6),'color',cc(2,:),'DisplayName','2');
set(handles.t2, 'Visible', 'off');

handles.t3=plot(handles.TempGraph,handles.Data.DataCell(:,7),handles.Data.DataCell(:,9),'color',cc(3,:),'DisplayName','3');
set(handles.t3, 'Visible', 'off');

legend(handles.PressureGraph,'hide');
legend(handles.TempGraph,'hide');

% Choose default command line output for GUI
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

And now for each checkbox call function I have the following code taken from previous forums :

function checkbox1_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% guidata(hObject, handles);

visstates = {'off', 'on'};
thisisvis = visstates{1 + get(hObject, 'Value')};

set(handles.p1, 'Visible', thisisvis);
set(handles.t1, 'Visible', thisisvis)

I am using the property 'DisplayName' for each plot to store the legend string. I looked on different topics and I guess there is something to put in place thanks to '-DynamicLegend' but no matter what I do, it is always showing the 3 legends on each plot even if only 1 checkbox is selected.

Any help would be very much appreciated.

Thanks.


Edit :

Benoit, I tried what you have suggested by creating a handles.LegendStrings Variable which contains a simple string for each of the 28 sets of data (and each set of data contains 6 lines) :

for k=1:6
for i=1:28
    handles.PressurePlots{i,k}=plot(handles.PressureGraph,handles.Data.Data{i,k}(:,1),handles.Data.Data{i,k}(:,2),'-',[handles.Data.Data{i,7}+handles.Data.Data{i,14} handles.Data.Data{i,7}+handles.Data.Data{i,14}],[min(handles.Data.Data{i,k}(:,2)) max(handles.Data.Data{i,k}(:,2))],'--',[handles.Data.Data{i,8}+handles.Data.Data{i,14} handles.Data.Data{i,8}+handles.Data.Data{i,14}],[min(handles.Data.Data{i,k}(:,2)) max(handles.Data.Data{i,k}(:,2))],'--',[handles.Data.Data{i,9}+handles.Data.Data{i,14} handles.Data.Data{i,9}+handles.Data.Data{i,14}],[min(handles.Data.Data{i,k}(:,2)) max(handles.Data.Data{i,k}(:,2))],'--',[handles.Data.Data{i,10}+handles.Data.Data{i,14} handles.Data.Data{i,10}+handles.Data.Data{i,14}],[min(handles.Data.Data{i,k}(:,2)) max(handles.Data.Data{i,k}(:,2))],'--',[handles.Data.Data{i,11} handles.Data.Data{i,11}],[min(handles.Data.Data{i,k}(:,2)) max(handles.Data.Data{i,k}(:,2))],'--',[handles.Data.Data{i,12}+handles.Data.Data{i,14} handles.Data.Data{i,12}+handles.Data.Data{i,14}],[min(handles.Data.Data{i,k}(:,2)) max(handles.Data.Data{i,k}(:,2))],'--',[handles.Data.Data{i,13}+handles.Data.Data{i,14} handles.Data.Data{i,13}+handles.Data.Data{i,14}],[min(handles.Data.Data{i,k}(:,2)) max(handles.Data.Data{i,k}(:,2))],'--','color',cc(i,:),'DisplayName',num2str(i));
    handles.LegendStrings{i}=num2str(i);
    set(handles.PressurePlots{i,k}, 'Visible', 'off');
end

end

Then creating my GetCheckBoxes vector :

GetCheckboxes = [get(handles.checkbox1,'Value') get(handles.checkbox2,'Value')  get(handles.checkbox3,'Value')  get(handles.checkbox4,'Value')  get(handles.checkbox5,'Value')  get(handles.checkbox6,'Value')  get(handles.checkbox7,'Value')  get(handles.checkbox8,'Value')  get(handles.checkbox9,'Value')  get(handles.checkbox10,'Value') get(handles.checkbox11,'Value') get(handles.checkbox12,'Value') get(handles.checkbox13,'Value') get(handles.checkbox14,'Value') get(handles.checkbox15,'Value') get(handles.checkbox16,'Value') get(handles.checkbox17,'Value') get(handles.checkbox18,'Value') get(handles.checkbox19,'Value') get(handles.checkbox20,'Value') get(handles.checkbox21,'Value') get(handles.checkbox22,'Value') get(handles.checkbox23,'Value') get(handles.checkbox24,'Value') get(handles.checkbox25,'Value') get(handles.checkbox26,'Value') get(handles.checkbox27,'Value') get(handles.checkbox28,'Value')];

and the TextLegend vector

TextLegend = (handles.LegendStrings(GetCheckboxes ==1))';

And for each checkbox callback function :

    function checkbox1_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% guidata(hObject, handles);
handles = guidata(gcf);
box=1;
GetCheckboxes = [get(handles.checkbox1,'Value') get(handles.checkbox2,'Value')  get(handles.checkbox3,'Value')  get(handles.checkbox4,'Value')  get(handles.checkbox5,'Value')  get(handles.checkbox6,'Value')  get(handles.checkbox7,'Value')  get(handles.checkbox8,'Value')  get(handles.checkbox9,'Value')  get(handles.checkbox10,'Value') get(handles.checkbox11,'Value') get(handles.checkbox12,'Value') get(handles.checkbox13,'Value') get(handles.checkbox14,'Value') get(handles.checkbox15,'Value') get(handles.checkbox16,'Value') get(handles.checkbox17,'Value') get(handles.checkbox18,'Value') get(handles.checkbox19,'Value') get(handles.checkbox20,'Value') get(handles.checkbox21,'Value') get(handles.checkbox22,'Value') get(handles.checkbox23,'Value') get(handles.checkbox24,'Value') get(handles.checkbox25,'Value') get(handles.checkbox26,'Value') get(handles.checkbox27,'Value') get(handles.checkbox28,'Value')];

visstates = {'off', 'on'};
thisisvis = visstates{1 + get(hObject, 'Value')};
TextLegend = (handles.LegendStrings(GetCheckboxes ==1))';



set(handles.PressurePlots{box,i}, 'Visible', thisisvis);
set(handles.TemperaturePlots{box,i}, 'Visible', thisisvis);
set(handles.PressurePlots{box,handles.SensorLocation}, 'Visible', thisisvis);
set(handles.TemperaturePlots{box,handles.SensorLocation}, 'Visible', thisisvis);


legend(handles.PressureGraph,TextLegend(:),'location','best')
legend(handles.TempGraph,TextLegend(:),'location','best')

But the problem is : -Legend are always the same color and not following the color of the plot line -It is pretty time consuming to check all the boxes at each checkbox callfunction to create the vector "GetCheckboxes"

Would you have an idea from what this would come ?

But it is updating the right value of the legend.

Thanks a lot for your help.

Marc.

1
Hey Marc so did my answer help you solve your problem? - Benoit_11
Hello Benoit. Please read my comment below your answer. Thanks a lot. - Marc
Oh sorry I did not see it! Ok I'll modify my code later today/tonight if you're still interested? - Benoit_11
Many thanks Benoit. Yes I am :) - Marc
Alright @Marc I modified my answer and I think that's what you were after. I commented the important parts so that should be quite clear. That was a nice question BTW! If my answer helped you please mark it as accepted thanks! - Benoit_11

1 Answers

1
votes

Here is some code which I hope does what you are looking for. I created a GUI programmatically so the syntax is a bit different from what you would get with GUIDE, but the idea is exactly the same. Each checkbox has its own callback, and when the user selects a particular checkbox the corresponding data is plotted, along with its associated title and legend. You can apply the code directly to your GUI without much modifications. Actually I did not use the 'DisplayName' property; Instead I created custom legend entries (and titles) in separate cells at the beginning of the GUI (i.e. like in your OpeningFcn) and then access the corresponding entry depending on which checkbox was selected. I think its more intuitive that way.

function GUI_CheckBox
clc
clear
close all

%// Create GUI components
handles.figure = figure('Position',[100 100 500 500],'Units','Pixels');

handles.axes1 = axes('Units','Pixels','Position',[60,90,400,300]);

handles.CB1 = uicontrol('Style','Checkbox','Position',[60 470 100 20],'String','Dataset 1','Value',1,'Callback',@CheckBox1Callback);
handles.CB2 = uicontrol('Style','Checkbox','Position',[60 440 100 20],'String','Dataset 2','Callback',@CheckBox2Callback);
handles.CB3 = uicontrol('Style','Checkbox','Position',[60 410 100 20],'String','Dataset 3','Callback',@CheckBox3Callback);

handles.xvalues = 1:20;

%// Create strings for legend and title for each data set.
handles.LegendStrings = {'Pressure case 1' 'Temperature case 1';'Pressure case 2' 'Temperature case 2';'Pressure case 3' 'Temperature case 3'};
handles.TitleStrings = {'Pressure & Temp case 1';'Pressure & Temp case 2';'Pressure & Temp case 3'};

handles.ColorArray = {'b' 'r';'--k' '--g';'+y' '+c'};

%// Generate dummy values
handles.PressureData = [rand(20,1) rand(20,1) rand(20,1)*.8];

handles.TempData = [rand(20,1) rand(20,1)*.9 rand(20,1)*.9];

%// Initially plot dataset 1
plot(handles.axes1,handles.xvalues,handles.TempData(:,1),handles.ColorArray{1,1})
hold on
plot(handles.axes1,handles.xvalues,handles.PressureData(:,1),handles.ColorArray{1,2})
hold off

%// Add corresponding title and legend
title(handles.TitleStrings(1));
legend(handles.LegendStrings(1,:));


guidata(handles.figure,handles);

    function CheckBox1Callback(~,~)

        handles = guidata(gcf);
        cla %// Clear current axes

        %// Get selected checkbox:
        GetCheckboxes = [get(handles.CB1,'Value') get(handles.CB2,'Value') get(handles.CB3,'Value')];


        for k = 1:numel(GetCheckboxes) %// If checkbox is checked, plot the data.

            hold on
            if GetCheckboxes(k)

                plot(handles.axes1,handles.xvalues,handles.TempData(:,k),handles.ColorArray{k,1});
                plot(handles.axes1,handles.xvalues,handles.PressureData(:,k),handles.ColorArray{k,2});

            end
            hold off
        end

        %// Fetch the right legend to add. Use transpose and colon operator
        %to get vertical array.

        TextLegend = (handles.LegendStrings(GetCheckboxes ==1,:))';
        legend(TextLegend(:),'location','best')
    end

    function CheckBox2Callback(~,~)

        handles = guidata(gcf);
        cla
        %// Get selected checkbox:

        GetCheckboxes = [get(handles.CB1,'Value') get(handles.CB2,'Value') get(handles.CB3,'Value')];

        for k = 1:numel(GetCheckboxes)

            hold on
            if GetCheckboxes(k)

                plot(handles.axes1,handles.xvalues,handles.TempData(:,k),handles.ColorArray{k,1});
                plot(handles.axes1,handles.xvalues,handles.PressureData(:,k),handles.ColorArray{k,2});

            end
            hold off
        end
        TextLegend = (handles.LegendStrings(GetCheckboxes ==1,:))';
        legend(TextLegend(:),'location','best')
    end

    function CheckBox3Callback(~,~)

        handles = guidata(gcf);
        cla

        %// Get selected checkbox:

        GetCheckboxes = [get(handles.CB1,'Value') get(handles.CB2,'Value') get(handles.CB3,'Value')];

        cla
        for k = 1:numel(GetCheckboxes)

            hold on
            if GetCheckboxes(k)

                handles.T(k) = plot(handles.axes1,handles.xvalues,handles.TempData(:,k),handles.ColorArray{k,1});
                handles.P(k) = plot(handles.axes1,handles.xvalues,handles.PressureData(:,k),handles.ColorArray{k,2});


            end
            hold off
        end
        TextLegend = (handles.LegendStrings(GetCheckboxes ==1,:))';
        legend(TextLegend(:),'location','best')
    end

end

Here is what it looks like when boxes 1 and 3 are checked:

enter image description here

And when boxes 2 and 3 are checked:

enter image description here

Everything is highly customizable of course. Hope that's what you were after!