Timer not working in my programmatic app (not app designer)

11 vues (au cours des 30 derniers jours)
Brendan Hall
Brendan Hall le 29 Sep 2023
Commenté : Voss le 29 Sep 2023
I have a programmatic app where I'm trying to periodically and automatically update a plot. Whenever I use the start(timer_object) it produces a message "Dot indexing is not supported for variables of this type". Here's the app:

Réponse acceptée

Voss
Voss le 29 Sep 2023
Modifié(e) : Voss le 29 Sep 2023
First, line 25:
%update_timer = data.update_timer;
needs to be uncommented for that error to happen (otherwise you get a different error because "update_timer" is undefined).
Errors in timer callbacks can be tricky to debug because the error message doesn't tell you what line it happened on. To debug it, you can put a breakpoint on the first line of the TimerFcn (axTimerFcn) and step through until you get the error. When you do that, you'll find that this line (line 31)
fig = ancestor(src,"figure","toplevel");
gives fig as an empty array [], which causes the error on the next line when you try to access fig.UserData. fig is empty because timers don't exist inside a figure the way uicontrols do, so ancestor is not going to work for them. You could use timerfind or timerfindall to find your timer object, but I recommend restructuring your code so that the callbacks (the uibutton ButtonPushedFcn StartTimer and the TimerFcn axTimerFcn) are nested inside the main function timer_app_1. Then they'll easily have access to whatever they need and it will no longer be necessary to have to store anything in the figure's UserData. Something like this:
function timer_app_1
fig = uifigure('Position',[100 50 2400 3.5*430],'AutoResizeChildren','off');
grid = uigridlayout(fig, [3 3]);
ax = uiaxes(grid);
ax.Layout.Column = 2;
ax.Layout.Row = 2;
uibutton(grid,"Text","Start Timer","ButtonPushedFcn",@StartTimer);
update_timer = timer('ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Period is 1 second
'BusyMode', 'queue',... % Queue timer callbacks when busy
'TimerFcn', @axTimerFcn);
%start(update_timer);
i=1;
function StartTimer(~,~)
start(update_timer)
end
function axTimerFcn(~,~)
i=i+1;
plot(ax,1:10,i.*ones(1,10))
if i==10
stop(update_timer)
end
end
end
  3 commentaires
Brendan Hall
Brendan Hall le 29 Sep 2023
Thanks!
Voss
Voss le 29 Sep 2023
You're welcome!

Connectez-vous pour commenter.

Plus de réponses (1)

Walter Roberson
Walter Roberson le 29 Sep 2023
The first parameter passed to a timer is the timer object, and the second parameter is the event data.
You are trying to
fig = ancestor(src,"figure","toplevel");
which is assuming that the first parameter is a graphics object rather than a timer object.
The easiest workaround is to use
update_timer = timer('ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Period is 1 second
'BusyMode', 'queue',... % Queue timer callbacks when busy
'TimerFcn', @(src,event)axTimerFcn(fig,event));
so that fig gets passed as the first parameter to the callback function.

Catégories

En savoir plus sur Develop Apps Using App Designer dans Help Center et File Exchange

Produits


Version

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by