I have a script called 'main.m' that basically takes the paths where I've saved all my images and insert them in arrays. It saves the images name in a .dat file and call a function named 'selectFolder.m'.
I posted all the script and functions under, my request is at the bottom.
%% Folders
imgFolder = './1.Dataset/';
functFolder = './2.Functions/' ;
%resFolder = './3.Results/';
%% Add path
addpath(genpath(imgFolder));
addpath(genpath(functFolder));
%% Listing Folders where my images are at
myFolder1 = '../Always'; %folder path
[..] %12 folders in total
myFolder12 = '../Random'; %folder path
%% Distinguish folder 'Always' & 'Random'
% Always Folders: subset of images for all users
mfA = {myFolder1, myFolder3, myFolder5, myFolder7, myFolder9, myFolder11};
dimA = length(mfA);
% Random Folders: subset of images randomly showed
mfR = {myFolder2, myFolder4, myFolder6, myFolder8, myFolder10, myFolder12};
dimR = length(mfR);
% check if folders are present
for i = 1:dimA
if ~isdir(mfA{i})
errorMessage = sprintf('Error: The following folder does not exist:\n%s', mfA{i});
uiwait(warndlg(errorMessage));
return;
end
end
for j = 1:dimR
if ~isdir(mfR{j})
errorMessage = sprintf('Error: The following folder does not exist:\n%s', mfR{j});
uiwait(warndlg(errorMessage));
return;
end
end
%% Take images and insert'em in Arrays
% Always
MyImgs1 = dir(fullfile(mfA{1}, '*.jpg'));
[..] %for every cell
MyImgs6 = dir(fullfile(mfA{6}, '*.jpg'));
% Random
MyImgs1r = dir(fullfile(mfR{1}, '*.jpg'));
[..] %for every cell
MyImgs6r = dir(fullfile(mfR{6}, '*.jpg'));
% create arrays with images names
Array_mfA = {MyImgs1.name, MyImgs2.name, MyImgs3.name, MyImgs4.name, MyImgs5.name, MyImgs6.name};
Array_mfR = {MyImgs1r.name, MyImgs2r.name, MyImgs3r.name, MyImgs4r.name, MyImgs5r.name, MyImgs6r.name};
%% Print content of array on file
fileIDA = fopen('2.Functions/Array_Always.dat','w');
formatSpec = '%s,';
nrows = length(Array_mfA);
for row = 1 : nrows
fprintf(fileIDA, formatSpec, Array_mfA{row});
end
fclose(fileIDA);
fileIDR = fopen('2.Functions/Array_Random.dat','w');
formatSpec = '%s,';
nrows = length(Array_mfR);
for row = 1 : nrows
fprintf(fileIDR, formatSpec, Array_mfR{row});
end
fclose(fileIDR);
%disclaimer
nrc = 1;
file = fopen('2.Functions/disclaimer.dat', 'w');
fprintf(file, '%d', nrc);
fclose(file);
%% call function
selectFolder(mfA, mfR);
This function takes two array as input, these array contains all the names of my images sorted. It does some operation and then it calls another function 'selectImage.m' that displays fullscreen the selected image.
function [] = selectFolder(mfA, mfR)
clc
%% Open Arrays from file
% Always
fileID = fopen('2.Functions/Array_Always.dat', 'rt');
Array_A = textscan(fileID,'%s', 'Delimiter', ',');
fclose(fileID);
% Random
fileID2 = fopen('2.Functions/Array_Random.dat', 'rt');
Array_R = textscan(fileID2,'%s', 'Delimiter', ',');
fclose(fileID2);
%% Show Disclaimer
file = fopen('2.Functions/disclaimer.dat', 'r');
dis = fscanf(file, '%d');
fclose(file);
if (dis == 1)
set(gcf,'Toolbar','none','Menubar','none', 'NumberTitle','off');
set(gcf,'units','normalized','outerposition',[0 0 1 1]);
hAx = gca;
set(hAx,'Unit','normalized','Position',[0 0 1 1]);
imshow('1.Dataset/Disclaimer/DIS.jpg');
drawnow;
nrc = 0;
file = fopen('2.Functions/disclaimer.dat', 'w');
fprintf(file, '%d', nrc);
fclose(file);
return;
end
%% select random folder from 'Array_A' aka Always Array
dimA = length(mfA);
if ~isempty(Array_A{1})
rndn = randperm(dimA, 1);
A_check = Array_A;
while isequal(A_check,Array_A)
Array_A = selectImage(mfA{rndn}, Array_A);
if isequal(A_check,Array_A)
rndn = randperm(dimA, 1);
end
end
fileIDA = fopen('2.Functions/Array_Always.dat','w');
formatSpec = '%s,';
nrows = cellfun('length', Array_A);
for row = 1 : nrows
fprintf(fileIDA, formatSpec, Array_A{1}{row});
end
fclose(fileIDA);
return;
end
%% select random folder from 'Array_R' aka Random Array
if ~isempty(Array_R{1})
dimR = length(mfR);
rndnr = randperm(dimR, 1);
R_check = Array_R;
while isequal(R_check,Array_R)
Array_R = selectImage(mfR{rndnr}, Array_R);
if isequal(R_check, Array_R)
rndnr = randperm(dimR, 1);
end
end
fileIDR = fopen('2.Functions/Array_Random.dat','w');
formatSpec = '%s,';
nrows = cellfun('length', Array_R);
for row = 1 : nrows
fprintf(fileIDR, formatSpec, Array_R{1}{row});
end
fclose(fileIDR);
end
end
selectImage:
function [ Array ] = selectImage( myFolder, Array )
%% Check
MyImgs = dir(fullfile(myFolder, '*.jpg'));
dim = length(MyImgs);
n = 0;
for i = 1 : dim
MyImgs(i).name
if ~any(strcmp(Array{1}, MyImgs(i).name))
disp(MyImgs(i).name);disp('not present in ');disp(myFolder);
n = n + 1;
end
end
if (n == dim)
disp('empty folder')
return;
end
rN = randperm(dim, 1);
baseFileName = MyImgs(rN).name;
while ~any(strcmp(Array{1}, baseFileName))
fprintf(1, 'not present %s\n', baseFileName);
rN = randperm(dim, 1);
baseFileName = MyImgs(rN).name;
end
%% Dispay image
dim = cellfun('length', Array);
for i = 1 : dim
if strcmp(baseFileName, Array{1}(i))
Array{1}(i) = [];
break
end
end
fullFileName = fullfile(myFolder, baseFileName);
fprintf(1, 'Now reading %s\n', fullFileName);
imageArray = imread(fullFileName);
set(gcf,'Toolbar','none','Menubar','none', 'NumberTitle','off');
set(gcf,'units','normalized','outerposition',[0 0 1 1]);
hAx = gca;
set(hAx,'Unit','normalized','Position',[0 0 1 1]);
imshow(imageArray); % Display image.
drawnow;
end
Now I have to integrate these functions in my gui. What I want to do is call the 'main.m' script just one time with a button like 'Let's Start' and with that will show the disclaimer.
Then repeat the process calling only the 'Next' button, which calls 'selectFolder.m' and display the images with the procedure described above.
Is it possibile to do it this way? I mean, how can I pass the variable 'mfA' and 'mfR' to selectFolder? Is there a better and simpler way to do it?
The code in the gui is like:
-main:
% --- Executes on button press in Start.
function Start_Callback(hObject, eventdata, handles)
% hObject handle to Start (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
axes(handles.axes1);
figure
main
-selectFolder:
function Next_Callback(hObject, eventdata, handles)
% hObject handle to Next (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
axes(handles.axes1);
figure %show the image in another window
selectFolder(mfA, mfR)
An easy way to share variables among the callback of a GUI is to use the
guidata function.
With respect to your specific variables mfA and mfR you can use guidata
to store them, this way: in the callback in which you generate the variables you want to share with other callback you can insert the following code:
% Get the GUI data
my_guidata=guidata(gcf);
%
% section of your code in which you create the mfA and mfR vars
%
% Store the variables to be shared among the callbacks in the guidata
my_guidata.mfA=mfA;
my_guidata.mfR=mfR;
% Save the updated GUI data
guidata(gcf,my_guidata);
In the callback in which you wnat to retreive the data, you can insert the
following code:
% Get the GUI data
my_guidata=guidata(gcf);
% Retrieve the data from the GUI data structure
mfA=my_guidata.mfA;
mfR=my_guidata.mfR;
In both the examples, the struct my_guidata holds the handles of the GUI and the additional varaibles you have defined.
With respect to the the architecture of the GUI, there are lots of possibilities.
Firt a comment: looking at the two callback you've posted at the bottom of your question, it seems that your GUI has, at least, one axes, nevertheless, you create, in both of them a new figure so it is not clear the role of that axes
Considering now your questions
What I want to do is call the 'main.m' script just one time with a button like 'Let's Start' and with that will show the disclaimer. Then repeat the process calling only the 'Next' button, which calls 'selectFolder.m' and display the images with the procedure described above
call the 'main.m' script just one time with a button like 'Let's Start' and with that will show the disclaimer
You have just to copy the relevant code of your main in the Start pushbutton callback.
Notice that the code which shows the disclaimer is actually in your selectFolder function, so you have to move it in the
Start callback.
Then repeat the process calling only the 'Next' button, which calls 'selectFolder.m' and display the images with the procedure described above
to do this, you have to remove the call to selectFolder from the main and move the body of your in the Next pushbotton callback.
Also you can copy the selectImage in the GUI .m file.
Hope this helps.
Qapla'
Related
I have a code that utilizes information taken over serial, compares it to a stored string, and then changes the color values of a panel in a GUI. this is done for 2 different panels. once the strcmp for both panels is 1, a button is enabled to close the GUI. i want to use a simple closereq() function to close it, but that wasn't working. to try something different, I commented out the closereq() and added in a disp('Success'). When pressing the button, Success will appear in the command window, but only after I manually pause the program from the editor panel.
this is my code:
function varargout = WorkingGUI3(varargin)
% WORKINGGUI3 MATLAB code for WorkingGUI3.fig
% WORKINGGUI3, by itself, creates a new WORKINGGUI3 or raises the existing
% singleton*.
%
% H = WORKINGGUI3 returns the handle to a new WORKINGGUI3 or the handle to
% the existing singleton*.
%
% WORKINGGUI3('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in WORKINGGUI3.M with the given input arguments.
%
% WORKINGGUI3('Property','Value',...) creates a new WORKINGGUI3 or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before WorkingGUI3_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to WorkingGUI3_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help WorkingGUI3
% Last Modified by GUIDE v2.5 02-Oct-2019 14:53:57
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', #WorkingGUI3_OpeningFcn, ...
'gui_OutputFcn', #WorkingGUI3_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before WorkingGUI3 is made visible.
function WorkingGUI3_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 WorkingGUI3 (see VARARGIN)
handles.uipanels = [handles.uipanel1, handles.uipanel2];
set(handles.pushbutton5, 'enable', 'off');
% Choose default command line output for WorkingGUI3
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes WorkingGUI3 wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = WorkingGUI3_OutputFcn(hObject, eventdata, handles)
delete(instrfind('Port', 'COM3'));
tag = serial('COM3');
fopen(tag);
BOX = char(zeros(2,14)); % matrix to be populated with incoming serial data
TrueValueData = 'C:\RfidChipTrueValues.xlsx';
[~,~,TrueValMat] = xlsread(TrueValueData);
% Creates matrix filled with the correct values
% indexed by box, which is the first row
% all proceeding rows are the master value
for i=1:inf
for n = 1:2
if i>10
readData = fscanf(tag);
if length(readData)>12
BOX(str2double(readData(8)),1:14)= readData(11:24);
if strcmp(TrueValMat{2,n}, BOX(n,:))
set(handles.uipanels(n), 'BackgroundColor', 'g');
else
set(handles.uipanels(n), 'BackgroundColor', 'r');
end
drawnow
if strcmp(TrueValMat{2,1}, BOX(1,:))...
&& strcmp(TrueValMat{2,2}, BOX(2,:)) == 1
set(handles.pushbutton5, 'enable', 'on');
end
end
end
end
end
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in pushbutton5.
function pushbutton5_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton5 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%closereq();
disp('It Works')
the final section
% --- Executes on button press in pushbutton5.
function pushbutton5_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton5 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%closereq();
disp('Success')
holds the callback to the button. I know its it correctly connected to the .fig because pressing the button makes Success appear, but only after manually pausing the program.
any help would be much appreciated.
As #Rotem showed, adding a pause after the first for loop successfully allowed the program to close.
I have function that checks for bottle cap. If there is no cap detected, it writes it as an image into folder. My problem is that if I pass different image, the old one get overridden with new one, is there a way to make new image instead of overwriting old one such as nocap0,jpg, then new one nocap1.jpg etc?
Code:
function [ ] = CHECK_FOR_CAP( image )
%crop loaction of cap
imageCROP = imcrop(image,[130 0 100 50]);
%turn to BW
imageBW=im2bw(imageCROP);
%count black pixels
answer = sum(sum(imageBW==0));
%if <250 black, save it to folder NOCAP
if answer<250
imwrite(image, 'TESTINGFOLDERS/NOCAP/nocap.jpg', 'jpg');
disp('NO CAP DETECTED');
end
UPDATE
I changed the code a bit now. Everytime I give a different image it now writes new one, BUT it overwrites the previous one aswell like so: http://imgur.com/a/KIuvg
My new code:
function [ ] = CHECK_FOR_CAP( image )
folder = 'TESTINGFOLDERS/NOCAP';
filePattern = fullfile(folder, '/*.*');
ImageFiles = dir(filePattern);
%crop loaction of cap
imageCROP = imcrop(image,[130 0 100 50]);
%turn to BW
imageBW=im2bw(imageCROP);
%count black pixels
answer = sum(sum(imageBW==0));
%if <250 black, save it to folder NOCAP
if answer<250
a = length(ImageFiles)-1;
for j = 1:a
baseFileName = [num2str(j),'.jpg'];
filename = fullfile(folder,baseFileName);
if exist(filename,'file')
imwrite(image,filename);
end
imwrite(image, fullfile(filename));
end
disp('NO CAP DETECTED');
end
You write
for j = 1:a
baseFileName = [num2str(j),'.jpg'];
filename = fullfile(folder,baseFileName);
if exist(filename,'file')
imwrite(image,filename);
end
imwrite(image, fullfile(filename));
end
This means that whenever you find a file, you overwrite it. Then you overwrite it again. You do this for as many files as exist (a comes from some dir you do on your folder). What you want is the opposite: find one that does not exist. Something like this:
j = 0;
while true
j = j + 1;
baseFileName = [num2str(j),'.jpg'];
filename = fullfile(folder,baseFileName);
if ~exist(filename,'file')
break
end
end
imwrite(image, fullfile(filename));
This could be further shortened (e.g., by looping while exist(...)) but it conveys the idea...
I have been trying to show an image after browsing it. However, I have been getting errors like:
??? Reference to non-existent field 'axes1'.
Error in ==> ImGui>Browse_Callback at 19
axes(handles.axes1)
??? Error while evaluating uicontrol Callback
I have tried working with both predefined axes [like 'axes(handles.axes1);'] as well as with post-defined [like 'imshow(imgorg, 'Parent', handles.axes1);']. Unfortunately, both techniques have not worked out for me and I am consistently stuck with axes. I also tried making a customized axes and work with that but it also failed to show my image on the figure. Can anyone please identify/ rectify the problem in my code:
function ImGui
f =figure('Visible','on','Position',[460,200,700,385]);
BrowseBt = uicontrol('Style','pushbutton',...
'String','Browse','Position',[600,350,70,25],...
'Callback',#Browse_Callback);
dispnames = uicontrol('Style','text','String','',...
'Position',[50,350,400,20]);
movegui(f,'center');
function Browse_Callback(hObject, eventdata, handles)
handles.output = hObject;
[FileName,PathName] = uigetfile('*.jpg;*.png','Select an image file',...
'C:\Users\owner\Downloads\Conjunctiva\SGRH');
fpname = strcat(PathName,FileName);
dispnames = uicontrol('Style','text','String',fpname,...
'Position',[50,350,400,20]);
imgorg = imread(fpname);
handles.output = hObject;
guidata(hObject, handles);
axes(handles.axes1);
imshow(imgorg);
% ImAxes = axes('Parent', f, ...
% 'Units', 'normalized', ...
% 'position',[50 50 400 250]);
% 'HandleVisibility','callback', ...
% imshow(imgorg, 'Parent', handles.axes1);
% imshow(imgorg, 'Parent', handles.ImAxes);
end
end
Use the guidata function.
and reorganize your code a little bit
You define all your uicontrols (button, textbox, axes etc ...) and you assign their handle to a structure (called handles here). Then when you GUI is fully defined, call guidata to store this handle structure in a place where any callback can access it.
Then in your callback function, call guidata again to retrieve this handle structure and get access to your objects (you axes and your textbox).
function ImGui
f =figure('Visible','on','Position',[460,200,700,385]);
handles.BrowseBt = uicontrol('Style','pushbutton',...
'String','Browse','Position',[600,350,70,25],...
'Callback',#Browse_Callback);
handles.dispnames = uicontrol('Style','text','String','',...
'Position',[50,350,400,20]);
handles.ImAxes = axes('Parent', f, ...
'Units', 'pixels', ...
'position',[30 30 640 300],...
'visible','off');
movegui(f,'center');
guidata(f,handles) ;
function Browse_Callback(hObject, eventdata)
handles = guidata(hObject);
[FileName,PathName] = uigetfile('*.jpg;*.png','Select an image file');
fpname = strcat(PathName,FileName);
imgorg = imread(fpname);
set(handles.dispnames,'String',FileName)
set(handles.ImAxes,'visible','on') ;
imshow(imgorg, 'Parent', handles.ImAxes);
guidata(hObject, handles);
end
end
In this specific case you don't really need to call guidata again at the end of the callback to store the values again but it is good practice, in case you modified something you want the changes to be saved.
I know that this is probably a simple problem but I am new to Matlab GUI's and basically want to get the old value which used to be stored in the text box to replace the value which has just been entered. E.g.
Text box contains a valid string,
User enters invalid string,
Callback func, validates input and realises new input is an error and reverts to the old previous value.
How should this be implemented or done? Atm I am just using the get and set property values.
Below is some sample code:
function sampledist_Callback(hObject, eventdata, handles)
% hObject handle to sampledist (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of sampledist as text
% str2double(get(hObject,'String')) returns contents of sampledist as a double
input = str2double(get(hObject,'String'));
if(input < 0 || input > 500)
errordlg('Sampled Dist. must be > 0 and < 500','Sample Dist - Input Error');
set(handles.sampledist,'String',['10']); %<--- I would like this value 10 to be the previous entry!
guidata(hObject,handles);
else
set(handles.sampledist,'String',['',input]);
guidata(hObject,handles);
end
Simply add a new field sampledistPrev to your handles structure.
In the openingFcn of the GUI, define the property with a line like this:
handles.sampledistPrev = 10; %# or whatever you choose as default value
%# if you want, you can set the default value to the GUI, so that you only need
%# to change it at one point, if necessary, like so:
set(handles.sampledist,'String',num2str(handles.sampledistPrev));
%# don't forget to save the handles structure at the end of the openingFcn
guidata(hObject,handles)
Then you update your callback like this:
function sampledist_Callback(hObject, eventdata, handles)
% hObject handle to sampledist (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of sampledist as text
% str2double(get(hObject,'String')) returns contents of sampledist as a double
input = str2double(get(hObject,'String'));
if(input < 0 || input > 500)
errordlg('Sampled Dist. must be > 0 and < 500','Sample Dist - Input Error');
set(handles.sampledist,'String',num2str(handles.sampledistPrev)); %reset value be the previous entry!
guidata(hObject,handles); %# Note that you don't need to save the handles structure unless
%# you have changed a user-defined value like sampledistPrev
%# It may still be useful to do it so you always remember
else
set(handles.sampledist,'String',['',input]);
%# also update the reset value
handles.sampledistPrev = input;
guidata(hObject,handles);
end
Why don't you store "the previous value" as the 'UserData' of that object, as follows:
function sampledist_Callback(hObject, eventdata, handles)
input = str2double(get(hObject,'String'));
if (input < 0 || input > 500)
errordlg('Sampled Dist. must be > 0 and < 500','Sample Dist - Input Error');
val=get(hObject,'UserData');
if isempty(val)
val='';
end
set(hObject,'String',val); %<--- This is where you'd like to set the previous entry value!
guidata(hObject,handles);
else
input=num2str(input);
set(handles.sampledist,'String',input,'UserData',input);
guidata(hObject,handles);
end
end
% Y.T.
I would like to create an animation which enables the user to go backward and forward through the steps of simulation.
An animation has to simulate the iterative process of channel decoding (a receiver receives a block of bits, performs an operation and then checks if the block corresponds to parity rules. If the block doesn't correspond the operation is performed again and the process finally ends when the code corresponds to a given rules).
I have written the functions which perform the decoding process and return a m x n x i matrix where m x n is the block of data and i is the iteration index. So if it takes 3 iterations to decode the data the function returns a m x n x 3 matrix with each step is stired.
In the GUI (.fig file) I put a "decode" button which runs the method for decoding and there are buttons "back" and "forward" which have to enable the user to switch between the data of recorded steps.
I have stored the "decodedData" matrix and currentStep value as a global variable so by clicking "forward" and "next" buttons the indices have to change and point to appropriate step states.
When I tried to debug the application the method returned the decoded data but when I tried to click "back" and "next" the decoded data appeared not to be declared.
Does anyone know how is it possible to access (or store) the results of the functions in order to enable the described logic which I want to implement in Matlab GUI?
Ultimately, this is a scoping of variables problem.
Global variables is rarely the right answer.
This video discusses the handles structure in GUIDE:
http://blogs.mathworks.com/videos/2008/04/17/advanced-matlab-handles-and-other-inputs-to-guide-callbacks/
This video discusses sharing of variables between GUIs and could apply to a single GUI problem also.
http://blogs.mathworks.com/videos/2005/10/03/guide-video-part-two/
The trick is to use nested functions so that they share the same workspace. Since I already started with an example in your last question, now I'm simply adding GUI controls to enable going forward/backward interactively, in addition to play/stop the animation:
function testAnimationGUI()
%# coordinates
t = (0:.01:2*pi)'; %# 'fix SO syntax highlight
D = [cos(t) -sin(t)];
%# setup a figure and axis
hFig = figure('Backingstore','off', 'DoubleBuffer','on');
hAx = axes('Parent',hFig, 'XLim',[-1 1], 'YLim',[-1 1], ...
'Drawmode','fast', 'NextPlot','add');
axis(hAx, 'off','square')
%# draw circular path
line(D(:,1), D(:,2), 'Color',[.3 .3 .3], 'LineWidth',1);
%# initialize point
hLine = line('XData',D(1,1), 'YData',D(1,2), 'EraseMode','xor', ...
'Color','r', 'marker','.', 'MarkerSize',50);
%# init text
hTxt = text(0, 0, num2str(t(1)), 'FontSize',12, 'EraseMode','xor');
i=0;
animation = false;
hBeginButton = uicontrol('Parent',hFig, 'Position',[1 1 30 20], ...
'String','<<', 'Callback',#beginButton_callback);
hPrevButton = uicontrol('Parent',hFig, 'Position',[30 1 30 20], ...
'String','<', 'Callback',#previousButton_callback);
hNextButton = uicontrol('Parent',hFig, 'Position',[60 1 30 20], ...
'String','>', 'Callback',#nextButton_callback);
hEndButton = uicontrol('Parent',hFig, 'Position',[90 1 30 20], ...
'String','>>', 'Callback',#endButton_callback);
hSlider = uicontrol('Parent',hFig, 'Style','slider', 'Value',1, 'Min',1,...
'Max',numel(t), 'SliderStep', [10 100]./numel(t), ...
'Position',[150 1 300 20], 'Callback',#slider_callback);
hPlayButton = uicontrol('Parent',hFig, 'Position',[500 1 30 20], ...
'String','|>', 'Callback',#playButton_callback);
hStopButton = uicontrol('Parent',hFig, 'Position',[530 1 30 20], ...
'String','#', 'Callback',#stopButton_callback);
%#----------- NESTED CALLBACK FUNCTIONS -----------------
function beginButton_callback(hObj,eventdata)
updateCircle(1)
end
function endButton_callback(hObj,eventdata)
updateCircle(numel(t))
end
function nextButton_callback(hObj,eventdata)
i = i+1;
if ( i > numel(t) ), i = 1; end
updateCircle(i)
end
function previousButton_callback(hObj,eventdata)
i = i-1;
if ( i < 1 ), i = numel(t); end
updateCircle(i)
end
function slider_callback(hObj, eventdata)
i = round( get(gcbo,'Value') );
updateCircle(i)
end
function playButton_callback(hObj, eventdata)
animation = true;
while animation
i = i+1;
if ( i > numel(t) ), i = 1; end
updateCircle(i)
end
end
function stopButton_callback(hObj, eventdata)
animation = false;
end
function updateCircle(idx)
set(hSlider, 'Value', rem(idx-1,numel(t))+1) %# update slider to match
set(hLine,'XData',D(idx,1), 'YData',D(idx,2)) %# update X/Y data
set(hTxt,'String',num2str(t(idx))) %# update angle text
drawnow %# force refresh
if ~ishandle(hAx), return; end %# check valid handle
end
%#-------------------------------------------------------
end
You might find the slider functionality a bit buggy, but you get the idea :)