Matlab GUI Callback Start and Completion - matlab

Is there a general purpose way to determine when a Matlab GUI callback function begins and then has returned to the dispatcher?
I want to lock out user interaction while callbacks are running to completion and also show busy status while callbacks are running. Is there a dispatcher accessible where I can insert this code, or do I have to put it into every callback function.
I am aware of the modal waitbar but I want to avoid using that as much as possible. (They can't be killed gracefully.)

I suggest to add a wrapper function, that wraps all original UIControl callback functions.
The wrapper function does the following:
Locks (disables) all GUI UIControl objects.
Executes original callback function.
Enables all GUI UIControl after original callback returns.
You can also start a timer before original callback, and stop the timer when callback returns (the timer can simulate a wait bar using an image built int to the main GUI [image inside a small axes]).
Example (assuming GUI was created using guide tool):
% --- Executes just before untitled1 is made visible.
function untitled1_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to untitled1 (see VARARGIN)
% Choose default command line output for untitled1
handles.output = hObject;
%Add wrapper function to each UIControl callback.
A = findall(hObject.Parent, 'Type', 'UIControl');
for i = 1:length(A)
set(A(i), 'Callback', {#wrapper, A(i).Callback});
end
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes untitled1 wait for user response (see UIRESUME)
% uiwait(handles.figure1);
function wrapper(ObjH, EventData, origCallback)
disp('Do somthing before callback begins...');
%You can also start a timer.
%Disable all UIControl objects, before executing original callback
A = findall(ObjH.Parent, 'Type', 'UIControl');
for i = 1:length(A)
set(A(i), 'Enable', 'off');
end
%Execute original callback.
feval(origCallback, ObjH, EventData);
disp('Do somthing after callback ends...');
%You can also stop the timer.
%Enable all UIControl objects, after executing original callback
for i = 1:length(A)
set(A(i), 'Enable', 'on');
end
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
pause(1);
set(handles.pushbutton1, 'BackgroundColor', [rand(1,1), rand(1,1), rand(1,1)]);

You can generally lock user interaction with the waitfor command. It is designed to do exactly what you ask.
You can make your callback function update a handle property when it's finished, which can cause waitfor to exit. If that handle property you're updating also happens to hold the result of a tic / toc operation timing the duration of your callback function, then you kill two birds with one stone :)

Related

How to return custom value from a GUIDE GUI

How do I return a custom value from a GUIDE GUI instead of the figure handle?
value = myGui();
Create the GUI you want (user controls, entry fields, processing logic, etc)
Modify the default GUIDE-generated code as follows (intentionally left out anything with no need to modify).
uiwait as last line in OpeningFcn()
function myGui_OpeningFcn(hObject, eventdata, handles, varargin)
... % anything else you may want to do
% Wait here until user completes gui calculation.
% Without pausing execution here, by default the figure handle
% would be immediately returned to the calling code.
uiwait();
Note: this will block execution in your calling code.
Package output value and call uiresume() in desired callback.
function btnReturnValue_Callback(hObject, ~, handles)
...
calcValue = doSomeCalculations();
% Set 'output' value which will be returned from this figure.
handles.output = calcValue;
% Update the 'guidata' so the handles.output value just set will be saved.
guidata(hObject, handles);
% Resume execution which was blocked by OpeningFcn().
uiresume();
Call the gui from some other code and store the resulting value.
value = myGui();
The returned value can be any matlab object (user class, struct, cell, etc).

matlab gui togglebutton stop while loop

I am having trouble stopping execution of a while-Loop which is activated by pressing a Togglebutton and is meant to stop when the Togglebutton is "untoggled".
The code inside calls a function that causes a steppermotor connected to an Arduino to do one step. The function needs about 10ms to execute.
Stopping works fine if i add a pause after the function call, but as the Onestep-function already needs longer to execute than I wish for and minimum pause-time is 10ms this solution isn't really pleasing.
% --- Executes on button press in Aplus_button.
function Aplus_button_Callback(hObject, eventdata, handles)
while get(hObject,'Value')
Onestep(1, 'Motor', handles)
% if i add a pause() here it works
end
I am thankful for any hints on how I get this executed as fast as possible.
Try adding a call to drawnow in your loop, where you have the pause. This should poll the GUI for any changes in state.
Since your Onestep function is so quick, you might only want to call drawnow only every 10th iteration (for example), depending on the GUI lag you can tolerate.
function button1_Callback(hObject, eventdata, handles)
% hObject handle to while_button1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
q=0;
while get(hObject,'value')
drawnow
q=q+1
end

Callback functions in a loop in MATLAB GUI

This is a MATLAB GUI. And I have a while loop running. But while in the loop i need to use keyboard inputs which are a different callback. Is there a way or is it possible to execute that callback while it is in the loop?
Note: I am using GUIDE
Yes, this is possible. You just need to get the character data from the keypress callback to the callback that is in a loop. One way of doing this is via the figure guidata.
For example, if your loop is running from a button callback and you want to see a keypress on the figure you could use the following:
Button Callback
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
fig = get(hObject,'Parent');
for i=1:1000
pause(0.01);
% Get the latest guidata
handles = guidata(fig);
if isfield(handles,'KeyData' ) && ~isempty(handles.KeyData)
fprintf(1,'Pressed : %s\n', handles.KeyData.Character);
% Clear the keydata we have now handled.
handles.KeyData = [];
guidata(fig,handles);
end
end
Figure keypress callback
% --- Executes on key press with focus on figure1 and none of its controls.
function figure1_KeyPressFcn(hObject, eventdata, handles)
% Store the keypress event data for use in the looping callback
handles.KeyData = eventdata;
guidata(hObject,handles);

reset ui value in Matlab GUI before changing to new value

So far, just say that I have a GUI and list of uicontrol in it with 1 push button that start the computation process. In the push button, the callback function look like this :
% --- Executes on button press in mulai.
function mulai_Callback(hObject, eventdata, handles)
% hObject handle to mulai (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%--give the program "Working" status
set(handles.status,'String','Working');
%--empty some edit text
set(handles.misklasifikasi,'String','');
set(handles.nilaiakurasi,'String','');
set(handles.nilaiwaktu,'String','');
%--Some computation process
%--Giving the result
set(handles.misklasifikasi,'String',misklasifikasi);
set(handles.nilaiakurasi,'String',sprintf('%g%% ',akurasi));
set(handles.nilaiwaktu,'String',sprintf('%g detik ',waktu));
%--give the program ready status
set(handles.status,'String','Ready');
but when I try it the program like just do the command after the computation process, did I missed something???
Thanks in advance...
Try to put a drawnow just before you start the computation. This will force MATLAB to flush the GUI event queue. You want to also place another call at the end of the callback function.

Making universal variables in MATLAB GUI

I'm kind of new to MATLAB and I'm doing some experiments for a school project.
What I want is a GUI with 3 buttons, when you press either of the first two, it adds up to one on a variable (one variable for each button), and when you press the third button, it does something with the variables from the first two buttons.
I used "guide" and dragged and dropped the buttons, and then I modified the functions.
But I realized that my variables only exist inside the function for the button, so if I initialize them they would restart everytime I press the button, and also there is no way for my third button to know the value of the first two.
Is there a way to make this variables always present? Or pass them from a function to another?
My code it's just the automatic code generated by "guide", with a v1 = v1+1; in the first button callback function and v2 = v2+1 in the second one, and disp(v1) disp(v2) in the third.
I hope you understand what I mean, I'm not a native english speaker so...
Anyway, thanks a lot, hope it's something easy to fix.
You have several options:
use global variables as nhowe suggested. But using global variables is not a good practice: see Top 10 MATLAB code practices that make me cry, or Wikipedia article
use setappdata / getappdata functions to store your variables (this is the simpler one)
learn how to use and properly update the handles structure that appears in each callback function for GUI controls created in GUIDE (this one is more complicated).
Here is an example of *.m file for case #3. Most of GUIDE-generated code was removed showing only things related to your variables. Basically, you have to update the handles structure in each callback function that does some changes to it with guidata(hObject, handles); line. After this all subsequent callbacks will see the updated handles structure.
function varargout = GUIProgramWithVariables(varargin)
% Here goes some comment from GUIDE
% Begin initialization code - DO NOT EDIT
% . . . actual code skipped
% End initialization code - DO NOT EDIT
% --- Executes just before GUIProgramWithVariables is made visible.
function GUIProgramWithVariables_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to GUIProgramWithVariables (see VARARGIN)
% Choose default command line output for GUIProgramWithVariables
handles.output = hObject;
% Here your code starts. It should be at the end of OpeningFcn
% Add your fields to handles structure
handles.C1 = 1;
handles.C2 = 2;
handles.C3 = 3;
% this updates modified handles structure
% so all subsequent call-backs will see the changes
guidata(hObject, handles);
% --- Executes on button press in Button1
function Button1_Callback(hObject, eventdata, handles)
% hObject handle to BrowseButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Here we do the magic with Button1
handles.C1 = handles.C1 + 1;
% this updates modified handles structure
% so all subsequent call-backs will see the changes
guidata(hObject, handles);
% --- Executes on button press in Button2
function Button1_Callback(hObject, eventdata, handles)
% hObject handle to BrowseButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Here we do the magic with Button2
handles.C2 = handles.C2 + 1;
% this updates modified handles structure
% so all subsequent call-backs will see the changes
guidata(hObject, handles);
% --- Executes on button press in Button3
function Button3_Callback(hObject, eventdata, handles)
% hObject handle to BrowseButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Here we do the magic with Button3
handles.C3 = handles.C1 + handles.C2;
% this updates modified handles structure
% so all subsequent call-backs will see the changes
guidata(hObject, handles);
The following is not the best practice for large complicated programs, but for something simple like what you're trying to do it sounds like global variables would be perfect. Say that X, Y, and Z are the variables you want to share between functions. Add the following at the beginning of every function that uses them, and they will all have access to the same values.
global X Y Z