Call OpeningFcn each time a button is pressed

Hi,
I have a piece of main code in which I call a GUI. In the GUI, the OpeningFcn function contains some code and calls uiwait:
handles.output = hObject;
% Set handles fields with initial values from UIcontrols
handles.speedrange = str2double(get(handles.editSpeedRange,'String'));
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes pitch_bounce_input_gui wait for user response (see UIRESUME)
uiwait(handles.bounce_pitch_fig);
The user can change a series of edit box values, which are all captured in the handles structure. When ready, a Run button is pressed that contains the uiresume line:
function pushRun_Callback(hObject, eventdata, handles)
% hObject handle to pushRun (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% resume code
uiresume(gcbf);
This executes the code in OutputFcn, which is some variable storage and manipulation, and returns to the main code. The main code runs a Simulink model in a loop, calculating a set of metrics from each run, and then produces a series of plots.
I would then like the user to have the option to press the Run button again, perhaps having adjusted some of the edit box values. However, the callback for the Run button just contains the uiresume command, which is now not paired to a uiwait. How do I call the OpeningFcn function again when the GUI has remained open (as I would like it to be)?
I haven't found reference to this problem anywhere so I'm concerned that it is less about finding the right code than correctly structuring it in the first place.
Thanks,
Simon.

3 Comments

Why not have you OpeningFcn initialize the GUI like it is supposed to do, and then have it call another function that pauses your GUI. Then you can have other functions/callbacks call your pausing function without having to run the rest of you OpeningFcn.
It also looks to me like this method is a bit vulnerable. Usually it is better to have getappdata and setappdata store the state (running or paused), and check that state every iteration of your loop. Then your buttons can modify that flag. Using guidata would also work, but you'll have to be careful with loading/overwriting the contents of the struct.
Hi Rik,
So should I put my handles updates in the pausing function and not in OpeningFcn?
I'm afraid I don't follow the second part of your answer, can you provide some more detail please (I'm new to Matlab)?
Regards.
I've not particularly tried to understand the problem here as I'm a bit short of time however my initial reaction on reading the question title was: don't do this.
The OpeningFcn is the function that is run when the figure is opened. Anybody reading the code will understand that it is its purpose. They will not expect that the function is going to run again just for a button press.
It is perfectly fine for the OpeningFcn and the button callback to both call the same function that will perform the same task on figure opening and button press but that common function shouldn't be call OpeningFcn. Don't surprise your reader.

Sign in to comment.

 Accepted Answer

Rik
Rik on 23 Oct 2018
There are two strategies I described:
  1. Have a function that you call at the end of OpeningFcn. That function only call uiwait, so it can also be run from other callbacks, making it easier to have a pause button.
  2. Don't use uiwait to pause your loop, but use a check at the start of your loop. The state of this check can be set and loaded with the getappdata function. Your pausing function would then use setappdata(gcbf,'BreakLoop',true) and inside your (infite?) loop you can use if getappdata(gcbf,'BreakLoop'),break,end. (Don't forget to set it back to false when you restart the loop.)

15 Comments

Thanks Rik, however, I think there is still some confusion.
The run button currently contains uiresume. Obviously, I wouldn't want it to call a function that contained uiwait as the purpose of the run button is to continue the code rather than pause it.
Once I've reached the end of my main code the first time around, can I call the GUI function that contains the uiwait from within my main code?
Regards,
Simon.
You should change what your run button callback does. It should set the flag and start the function that runs the loop. So you'll have this list of functions:
  1. OpeningFcn - initializes GUI and sets setappdata(gcbf,'BreakLoop',true) (or if you want it to start with the loop: set to false and call LoopFcn)
  2. RunButtonCallback - sets setappdata(gcbf,'BreakLoop',false) and calls LoopFcn
  3. LoopFcn - loops the actual calculation (e.g. with while true) and on every iteration of the while loop it starts with if getappdata(gcbf,'BreakLoop'),break,end
  4. PauseFcn - sets setappdata(gcbf,'BreakLoop',true) so the loop will stop when it finishes its current iteration.
So you won't have any uiwait or uiresume anywhere in your code.
Many thanks Rik, I'll give it a go.
Regards.
Hi Rik,
The loop in question is in the main code and not in the GUI code. In your previous response, where were you siting the LoopFcn function?
Regards,
Simon.
As long as you can edit that main code to include the break it doesn't matter that the loop code is in a separate file.
Ok. I think I'm beginning to see how it should be constructed.
Presumably, since I'm not going to use uiwait and since, if I don't start with the loop, OutputFcn will automatically run after OpeningFcn, I must avoid having any code in my main script after the GUI call as this will automatically run.
This will effectively force me to place all my code within the GUI and separate scripts/functions. Is this a correct assumption?
Regards.
I don't know if I understand what you mean. In Matlab, a GUI built with GUIDE is not special, but just normal Matlab. Just a figure with some fancy visuals that run a function if you interact with them.
That means that you can run any function you like as a callback function, or have that function call any script/function you like. The upside of functions is that they are self-contained: they have a pre-defined input and output.
How you extract the data out of you GUI is up to you. You can use guidata together with the handle to the GUI, save the results in the appdata, or even save the results in a mat-file.
Let me explain a different way. My current code is arranged thus:
Main script > calls gui
Gui OpeningFcn > sets some fields in handles, calls uiwait
User tinkers with gui
Run button callback > calls uiresume
Gui OutputFcn > copies contents of handles fields to variables for some manipulation, those variables are assigned to the base workspace using assignin
Main script > runs Simulink model, calculates metrics
At this point, as per my original post, I wanted the user to be able to press the run button again and get the same response. Clearly, the above arrangement doesn't allow for that.
Now, if I do not use uiwait then OutputFcn and the remainder of my main script will run before the user has a chance to tinker with the gui.
This is the point to my last post.
Regards.
Hi Rik,
Can I also ask: if you look at your response here: https://uk.mathworks.com/matlabcentral/answers/425579-call-openingfcn-each-time-a-button-is-pressed#comment_626755
From where are you calling PauseFcn?
I'm afraid I can't workout which functions call which in order to have a loop that's stalled until the run button is pressed.
Regards.
You will indeed have to split this input its constituent parts, unless you want to make your GUI modal (which you don't want to).
Everything that happens after uiresume in your original setup needs to be self-contained, which is easiest to do if it inside a single function that extracts its input from the GUI.
PS in that comment PauseFcn was intended to be a button callback
Ok, thanks Rik. I have a new structure to try in which the Pause function is called in the loop and so doesn't require a button press.
Unfortunately, I've immediately run into trouble. I call the gui from my main code and it appears and instantly disappears. On debugging, it has already disappeared before the first line of OpeningFcn has run.
All other code has been blocked out except for the gui callbacks. I haven't a clue how to debug any more than I have. Any ideas?
If this should go in a separate question then I'd be happy to do that.
Regards.
I have no clue why you would put the pause function inside the loop. Wasn't the whole idea that you wanted to run the loop, but also be able to pause its execution? If that is the case putting the pause inside the loop doesn't do anything useful.
If you don't intend to follow my advice about the structure of your code, please explain why. It is frustrating to spend time helping you if you seem to ignore most of it.
Restarting Matlab might solve your issue, otherwise use the debugger inside your 'main code' to go through it step by step to see where exactly something unexpected happens.
I can add that on further debugging the gui appears and disappears at the following line in gui_mainfcn:
gui_hFigure = local_openfig(gui_State.gui_Name, gui_SingletonOpt, gui_Visible);
Does this help?
Regards.
I am following your advice, and am grateful for it. Don't be frustrated as you are helping fantastically - obviously more than you realise.
I am new to this so don't take my proposed structure as a given - it could all fall over as I begin to develop it.
However, to answer your point: yes, I want to pause the code, but I don't want the user to be responsible for that. The user will only have a run button. After executing the calculations the code will pause itself. This is as I explained it above.
Regards.
In your other thread I think we have identified the root cause of the premature exit, so I'll ignore it here.
You can have the pause automatically trigger, but I would suggest you first make sure that your code runs without error when you separate the code that should run after the resume from the rest. That way you can simply call that code if you want to re-run the analysis with the same or with changed parameters.

Sign in to comment.

More Answers (0)

Categories

Find more on Programming in Help Center and File Exchange

Products

Release

R2017b

Asked:

on 23 Oct 2018

Commented:

Rik
on 24 Oct 2018

Community Treasure Hunt

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

Start Hunting!