How to save and load App Designer app state in between sessions

I've seen similar questions about how to save/load variables from an app, but I couldn't find a way to save the state of my app (including all variables, all states of edittexts, etc) when the app is closed, and loading it when it's started. I tried the following code, with no luck. I thought that by just giving a name to the file it would by default save everything, but when I try to access the file just saved I get the app with the same structure as the previous, but all properties have: The variable app.something does not exist. Also, how can i clear all properties values and set everything to the state the app would be if no file was loaded?
function startupFcn(app)
try
load('tccworkspace.mat');
catch
return;
end
end
function ElementosUIFigureCloseRequest(app, event)
delete(app);
save('tccworkspace.mat');
end

2 Commenti

but all properties have: The variable app.something does not exist
Well, yes, before saving your mat file you delete the app object, in effect making the app handle invalid. I suspect it would work a bit better if you delete the app after you save it to a file.
I can't comment on the rest of your question as I don't know enough about the App designer.
I noticed that mistake shortly after posting. Unfortunately, changing the order didn’t help, as I’ve explained in my reply to the other answer.

Accedi per commentare.

Risposte (1)

You should load your .mat file into a structure, and pass that structure to other functions.
S=load('tccworkspace.mat');
You can set S to a property of your app to access it in other functions.

5 Commenti

The problem is it seems I can't even save it. I'm trying to save everything at once, but when I do so, I get this message:
Warning: Functionality not supported with figures created with the uifigure function. For
more information, see Graphics Support in App Designer.
Just by trying to use the code posted above. The same applies to trying to load the file after saving. Do I have to manually save every single parameter I'd like and load it again or is there a way to conveniently save everything (what I'm referring as the "state") of the app to be reopened exactly like it was before closing? By the way, the only UIFigure I have is the "canvas" where everything is being put.
Just as a followup, for some reason, after trying it again with the same code, I'm able to save and load everything. The problem is I can't override the current "app" with the "app" that I've loaded. For example, if I try:
S=load('tccworkspace.mat')
app.sy = S.app.sy;
Absolutely nothing happens. (sy is a numeric EditField). But if I try the following:
S=load('tccworkspace.mat')
app.sy.Value = S.app.sy.Value;
The value is loaded just as expected. The problem is that I have around 200+ variables, and I don't think doing this manually for every single one would be the most efficient method, as I'd also like to handle Visibility and other parameters. The weird thing is that analyzing both 'app.sy' and 'S.app.sy', I get EXACTLY THE SAME PROPERTIES, as shown below:
K>> app.sy
ans =
NumericEditField (60) with properties:
Value: 60
ValueDisplayFormat: '%11.4g'
RoundFractionalValues: 'off'
Limits: [0 Inf]
LowerLimitInclusive: 'on'
UpperLimitInclusive: 'on'
ValueChangedFcn: ''
Position: [161 348 60 22]
Show all properties
BackgroundColor: [1 1 1]
BeingDeleted: 'off'
BusyAction: 'queue'
CreateFcn: ''
DeleteFcn: ''
Editable: 'on'
Enable: 'on'
FontAngle: 'normal'
FontColor: [0 0 0]
FontName: 'Helvetica'
FontSize: 12
FontWeight: 'normal'
HandleVisibility: 'on'
HorizontalAlignment: 'right'
InnerPosition: [161 348 60 22]
Interruptible: 'on'
Limits: [0 Inf]
LowerLimitInclusive: 'on'
OuterPosition: [161 348 60 22]
Parent: [0×0 GraphicsPlaceholder]
Position: [161 348 60 22]
RoundFractionalValues: 'off'
Tag: ''
Type: 'uinumericeditfield'
UpperLimitInclusive: 'on'
UserData: []
Value: 60
ValueChangedFcn: ''
ValueDisplayFormat: '%11.4g'
Visible: 'on'
K>> S.app.sy
ans =
NumericEditField (60) with properties:
Value: 60
ValueDisplayFormat: '%11.4g'
RoundFractionalValues: 'off'
Limits: [0 Inf]
LowerLimitInclusive: 'on'
UpperLimitInclusive: 'on'
ValueChangedFcn: ''
Position: [161 348 60 22]
Show all properties
BackgroundColor: [1 1 1]
BeingDeleted: 'off'
BusyAction: 'queue'
CreateFcn: ''
DeleteFcn: ''
Editable: 'on'
Enable: 'on'
FontAngle: 'normal'
FontColor: [0 0 0]
FontName: 'Helvetica'
FontSize: 12
FontWeight: 'normal'
HandleVisibility: 'on'
HorizontalAlignment: 'right'
InnerPosition: [161 348 60 22]
Interruptible: 'on'
Limits: [0 Inf]
LowerLimitInclusive: 'on'
OuterPosition: [161 348 60 22]
Parent: [0×0 GraphicsPlaceholder]
Position: [161 348 60 22]
RoundFractionalValues: 'off'
Tag: ''
Type: 'uinumericeditfield'
UpperLimitInclusive: 'on'
UserData: []
Value: 60
ValueChangedFcn: ''
ValueDisplayFormat: '%11.4g'
Visible: 'on'
The weird thing is, when I try to compare both properties, I get 0 as a result instrad of 1, so there actually is something different which is probably why I can't assign one to the other. I just can't figure out what/why
app.sy == S.app.sy
ans =
logical
0
Any progress on this front? I'm having the same problem and would love to hear any possible solutions!
Hello !
I am having the same problem, so far I solved it by using the setfield method, manually for all of the property of the element of the app. It is not so clean but it does the job...
If there is a cleaner version I would be interested !
Thanks
I wrestled with this issue for a while as well, I think I've got a work-around.
I only cared about the value and visibility of each app property, so that what I save and load.
function SaveButtonPushed(app, event)
props = properties(app);
values = cell(1, length(props));
visibilities = cell(1, length(props));
for i = 1:length(props)
propName = props{i};
property = app.(propName);
if isprop(property, 'Value')
values{i} = app.(propName).Value;
end
if isprop(property, 'Visible')
visibilities{i} = app.(props{i}).Visible;
end
end
file = uiputfile('*.mat', "Save Message" );
if file
save(file, 'props', 'values', 'visibilities');
end
end
function LoadButtonPushed(app, event)
file = uigetfile('*.mat', "Load Message");
if file
load(file, 'props', 'values', 'visibilities');
end
for i = 1:length(props)
propName = props{i};
property = app.(propName);
if isprop(property, 'Value')
app.(propName).Value = values{i};
end
if isprop(property, 'Visible')
app.(props{i}).Visible = visibilities{i};
end
end
end

Accedi per commentare.

Categorie

Scopri di più su Develop Apps Programmatically in Centro assistenza e File Exchange

Prodotti

Release

R2016b

Richiesto:

il 17 Giu 2019

Commentato:

il 20 Lug 2020

Community Treasure Hunt

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

Start Hunting!

Translated by