1

I've been thinking how I could update in Matlab the legend of my plots as the for goes on, basically, I have a for which creates a graph that is added to the plot (using hold on) in every iteration, I'd like to update the legend of the aforementioned plot. This is how I've done it:

clear all; close all; clc;

x0 = 10;
t = linspace(0, 2, 100);
v0 = 0;
g = [10:10:100];
str = [];

hold on
for i = 1:length(g)
    x = x0 + v0*t - 1/2*g(i)*t.^2;
    v = v0 - g(i)*t;
    plot(t, x)
    axis([0, 2, -200, 10]);
    str = [str, sprintf("g = %d", g(i))];
    legend(str, 'Location','southwest');
    pause(0.3);
end
hold off

i.e. using that size-changing string str. I have a feeling that there is a better and more performant way of doing this but I don't know how else to approach the problem.

2 Answers 2

2

Use DisplayName in the plot function, and toggle AutoUpdate in legend. This is my attempt of your for-loop:

for i = 1:length(g)
    x = x0 + v0*t - 1/2*g(i)*t.^2;
    v = v0 - g(i)*t;
    plot(t, x,'DisplayName',sprintf("g = %d", g(i)));
    axis([0, 2, -200, 10]);
%     str = [str, sprintf("g = %d", g(i))];
%     legend(str, 'Location','southwest');
    legend('Location','southwest','AutoUpdate',1);
    pause(0.3);
end
1
  • Much better than my solution. Welcome to the site!
    – Luis Mendo
    Commented Mar 29, 2022 at 20:37
0

An improvement would be to update the String property of the legend, instead of creating a new legend in each iteration. This "update instead of re-create" idea is common practice for graphical objects that change with time, and results in faster execution. In your example code this will hardly have any impact, but it still looks like a cleaner approach:

clear all; close all; clc;

x0 = 10;
t = linspace(0, 2, 100);
v0 = 0;
g = [10:10:100];
str = [];

le = legend(str, 'Location','southwest'); %%% new: create empty legend
hold on
for i = 1:length(g)
    x = x0 + v0*t - 1/2*g(i)*t.^2;
    v = v0 - g(i)*t;
    plot(t, x)
    axis([0, 2, -200, 10]);
    str = [str, sprintf("g = %d", g(i))];
    le.String = str; %%% changed: update String property of the legend
    pause(0.3);
end
hold off

Alternatively, you can avoid storing str, and directly append the new part to the legend. Again, the main reason for this is that the code arguably looks cleaner, as you avoid keeping the same information in two places (the variable and the graphical object):

clear all; close all; clc;

x0 = 10;
t = linspace(0, 2, 100);
v0 = 0;
g = [10:10:100];
% str = []; %%% removed

le = legend(str, 'Location','southwest'); %%% new: create empty legend
hold on
for i = 1:length(g)
    x = x0 + v0*t - 1/2*g(i)*t.^2;
    v = v0 - g(i)*t;
    plot(t, x)
    axis([0, 2, -200, 10]);
    % str = [str, sprintf("g = %d", g(i))]; %%% removed
    le.String = [le.String  sprintf("g = %d", g(i))]; %%% changed: append new string
    pause(0.5);
end
hold off

As a side note, speaking of performance, you may want to replace clear all by clear; see relevant links: 1, 2, 3.

Not the answer you're looking for? Browse other questions tagged or ask your own question.