App - changing button state when a uifigure is closed

When the user presses a state button, a UIfigure is generated. When the user closes that UIfigure, I want to reset the state of the button. I think I have a syntax error somewhere- any assistance is much appreciated. First is the code for the button press, next is the code for the function.
%T0 Switch on/off recording of script
if app.RecordScriptButton.Value==1
app.RecordScriptButton.BackgroundColor='green';
app.RecordScriptButton.Text='Recording';
app.ScriptContent={'%Paste the following text in the main workspace and press <enter> to run the script.'};
app.ScriptWindow= uifigure('Position',[100 100 420 420],'Name','Script');
set(app.ScriptWindow,'CloseRequestFcn',closeScriptFcn);
app.ScriptTextArea = uitextarea(app.ScriptWindow,'Value', app.ScriptContent,'Position',[10 10 400 400],'FontSize',12,'FontWeight','bold');
else
app.RecordScriptButton.BackgroundColor='red';
app.RecordScriptButton.Text='Record Script';
%Close window and erase the script for next use - use try in case user has already closed window
try
close(app.ScriptWindow);
end
end
%function code, located at start of app code.
function closeScriptFcn(app)
app.RecordScriptButton.Value=0;
app.RecordScriptButton.BackgroundColor='red';
close(app.ScriptWindow);
end

5 件のコメント

Geoff Hayes
Geoff Hayes 2018 年 7 月 12 日
編集済み: Geoff Hayes 2018 年 7 月 12 日
Jessica - are you observing some kind of error when you try this? Is the closeScriptFcn not being called? Perhaps you need to prepend an @ before your callback like
set(app.ScriptWindow,'CloseRequestFcn',@closeScriptFcn);
(though I'm not sure that is necessary with your version of MATLAB).
Jessica Hiscocks
Jessica Hiscocks 2018 年 7 月 12 日
I forgot to mention that my version is 2016b. With the original code above, I get the error 'Undefined function or variable 'closeScriptFcn' when I press the RecordScriptButton. If I add an @ as per your statement above, there are no error messages but no actions are taken when the script window 'x' is pressed (still, this is an improvement). When the script window 'x' is pressed the following message appears in the matlab command window:
Warning: Error occurred while executing the listener callback for event Custom defined for class asyncio.Channel:
Index exceeds matrix dimensions.
Geoff Hayes
Geoff Hayes 2018 年 7 月 12 日
Can you put a breakpoint at the first line in the closeScriptFcn callback and then run your code and close the app to see if the debugger pauses at your breakpoint? It isn't clear to me which line of code is generating the Index exceeds matrix dimensions. messsage...
Jessica Hiscocks
Jessica Hiscocks 2018 年 7 月 12 日
編集済み: Jessica Hiscocks 2018 年 7 月 12 日
Changed the function code as per below. No display commands ran, so the function isn't even being called properly. It's possible this has something to do with the way functions are called in the app, functionname(app) is the usual syntax. But that doesn't work either.
function closeScriptFcn(app)
disp('Function Activated')
app.RecordScriptButton.Value=0;
disp('Script button reset')
app.RecordScriptButton.BackgroundColor='red';
disp('button coloured')
close(app.ScriptWindow);
disp('Script window closed')
end
Geoff Hayes
Geoff Hayes 2018 年 7 月 13 日
I haven't used App Designer so can't comment on why this might not be working. I suppose that when you create the figure, you could assign the callback there
app.ScriptWindow= uifigure('Position',[100 100 420 420],'Name','Script', 'CloseRequestFcn',@closeScriptFcn);
though I'm not sure if that will make a difference. You can confirm that
close(app.ScriptWindow);
is being called? And there aren't any other warnings or errors in the command window that might explain why the CloseRequestFcn is not being called?

サインインしてコメントする。

 採用された回答

Sean de Wolski
Sean de Wolski 2018 年 7 月 26 日

0 投票

A perfect case for events and listeners. Add a listener for the ObjectBeingDestroyedEvent of the new uifigure.
app.ScriptWindow = uifigure;
addlistener(app.ScriptWindow, 'ObjectBeingDestroyed', @(~,~)disp('hello world'))
Replace the disp statement with setting your button state to the desired.

5 件のコメント

Jessica Hiscocks
Jessica Hiscocks 2018 年 7 月 26 日
Nope! Tried the following, got 'the object to the left of the equals sign is not a valid target for an assignment'.
addlistner(app.ScriptWindow,'ObjectBeingDestroyed',@(~,~)app.RecordScriptButton.Value=0);
Sean de Wolski
Sean de Wolski 2018 年 7 月 27 日
You can't have the = sign for assignment in an anonymous function. Use the set command:
@(~,~)set(app.RecordScriptButton, 'Value', 0);
Alternatively, you could create another function that you call that uses = (for more complex logic) but for this set is the best way to do it.
Jessica Hiscocks
Jessica Hiscocks 2018 年 7 月 27 日
Unfortunately now I get the error message Undefined function 'addlistner' for input arguments of type 'matlab.ui.Figure'. Maybe 2016 doesn't support this function? Code for that callback is below.
As another approach, I tried to use functions. If I was instead to call a function when creating the window, what would the syntax be? I made a stab at it below, but neither of these is correct.
app.ScriptWindow= uifigure('Position',[100 100 420 420],'Name','Script','CloseRequestFcn',@(~,~)my_closereq);
or
app.ScriptWindow= uifigure('Position',[100 100 420 420],'Name','Script','CloseRequestFcn',@(app,app.ScriptWindow,~)my_closereq);
Thanks for your help, this is pretty complex.
%T0 Switch on/off recording of script
if app.RecordScriptButton.Value==1
app.RecordScriptButton.BackgroundColor='green';
app.RecordScriptButton.Text='Recording';
app.ScriptContent={'%Paste the following text in the main workspace and press <enter> to run the script.'};
fig=uifigure('Position',[100 100 420 420],'Name','Script');
addlistner(fig,'ObjectBeingDestroyed',@(~,~)set(app.RecordScriptButton,'Value',0));
app.ScriptWindow=fig;
app.ScriptTextArea = uitextarea(app.ScriptWindow,'Value', app.ScriptContent,'Position',[10 10 400 400],'FontSize',12,'FontWeight','bold');
else
app.RecordScriptButton.BackgroundColor='red';
app.RecordScriptButton.Text='Record Script';
%Close window and erase the script for next use
close(app.ScriptWindow);
end
Sean de Wolski
Sean de Wolski 2018 年 7 月 27 日
Typo: addlistener not addlistner. However, since MathWorks is headquartered outside of Boston, we should have "addlisnah"!
Jessica Hiscocks
Jessica Hiscocks 2018 年 7 月 27 日
Thank you, this worked. At which point I realised I actually had several commands that needed to execute when the window closed, so I needed to call a function instead. With the syntax you gave me above, I managed to get that to work too. For anyone else's future reference, that is as per below:
addlistener(app.ScriptWindow,'ObjectBeingDestroyed',@(~,~) closeScriptFcn(app,4));
For a function that starts
function closeScriptFcn(app,~)
The 4 is a dummy variable since the app function needs two arguments, and the addlistener doesn't seem to like having a ~ there. Thank you again for sticking it out with this problem.

サインインしてコメントする。

その他の回答 (1 件)

Dennis
Dennis 2018 年 7 月 13 日

0 投票

I would actually expect a couple of error messages.
app.ScriptWindow= uifigure('Position',[100 100 420 420],'Name','Script');
1.) If ScriptWindow does not already exist at this point, you should not be able to add ScriptWindow to the existing app structure in appdesigner ('Unrecognized proberty 'ScriptWindow'...).
2.) Consider this would work!
You never actually update app. When you run your function a second time (else part) app.ScriptWindow either does not exist or does not point to your uifigure.
3.) Callback functions in MATLAB always need atleast 2 input arguments:
function closeScriptFcn(app,~)
%code
end
If this function was ever called you should have received 'Not enough input arguments'.
I want to suggest an alternative route:
value = app.Button.Value;
if value==1
ScriptWindow=uifigure();
setappdata(app.Button,'h',ScriptWindow)
waitfor(ScriptWindow)
app.Button.Value=0;
else
ScriptWindow=getappdata(app.Button,'h');
close(ScriptWindow)
end
This should work, and does not require another callback function. You could call a function after waitfor().

1 件のコメント

Jessica Hiscocks
Jessica Hiscocks 2018 年 7 月 26 日
Hello Dennis, sorry for the late reply. To address your points in order. 1. This line causes the app to open a new window, separate from the app GUI, which is the desired behaviour. 2. Since this is a new window, there's no need to update anything. 3. This is indeed an error in the code, so I've fixed that.
Your code seems like it will close the window if the button state is changed. I have already set that function up, what I need is the opposite: if the Window is closed, I need to change the button state.
If I'm missing something here or you have any suggestions, please let me know.

サインインしてコメントする。

カテゴリ

ヘルプ センター および File ExchangeCreating, Deleting, and Querying Graphics Objects についてさらに検索

タグ

Community Treasure Hunt

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

Start Hunting!

Translated by