I made a GUI that gets 2 elements: files (list of files) and options (I will explain later).
there is a function that calls the function below:
// asume that this is my 'options'
options{1} = {'Treatment', 't1', 't2'};
options{2} = {'Tree', '1', '2'};
options{3} = {'Replica', 'r1', 'r2', 'r3'};
// asume that this is my 'files' (may be more than 2 images
files{1} = 'C:\Documents and Settings\erezalon\Desktop\gib_proj_02.10.12\fina3_32bit\IMG_4640.JPG';
files{2} = 'C:\Documents and Settings\erezalon\Desktop\gib_proj_02.10.12\fina3_32bit\grapes03.jpg';
mydata = mainGUI(options, files).
// here I want to check 'mydata'. if it is equal to zero or not.
for each image, the GUI is created in the function 'mainGUI' (but each time, one GUI is showed till the user presses 'next').
I want to do the next thing:
if the user presses the close button in the GUI, I want to stop the displaying of the other GUI-s and set 'data = 0'. then, I will check what is the returned element ('mydata') and if it's equal to 0, I will know that the user closed the GUI and I will act as needed.
I tried to do this by the 'cmdClose_Callback' but it doesn't work.
assume that 'files' = two images, so this is the GUI of the first image.
I press the close button:
and got the GUI of the second image despite of closing the GUI of the first image.
I want that when I close the GUI, the other GUI-s don't appear.
this is my code:
function data = mainGUI(options, files)
%# current options
j = 1;
ops = cellfun(#(c) c(1), options, 'Uniform',false);
data{j} = [ops{1:length(ops)}];
j = j + 1;
options = cellfun(#(c) c(2:1:end), options, 'Uniform',false);
clear ops;
ops = cellfun(#(c) c(1), options, 'Uniform',false);
opts = [ops{1:length(ops)}];
%# create main figure, with plot and options button
hFig = figure('Name','window 1','Visible','Off');
a = 1
callback
%# options button callback function
function callback(o,e)
a = 2
%# save current options (sharing data between the two GUIs)
setappdata(hFig, 'opts',opts);
%# display options dialog and wait for it
for k=1: length(files)
hOptsGUI = secondaryGUI(hFig, options, k, length(files));
img = imread(files{k}); %# Read the data from image file data
hAxes = axes('Parent',hOptsGUI,'Units','pixels','Position',[362 242 424 359]); %# so the position is easy to define
image(img,'Parent',hAxes); %# Plot the image
set(hAxes,'Visible','off'); %# Turn the axes visibility off
a = 3
waitfor(hOptsGUI);
a = 4
%# get new options, and update plot accordingly
opts = getappdata(hFig, 'opts');
data{j} = opts;
j = j + 1;
end
end
end
function hFig = secondaryGUI(hParentFig, options, k, num_files)
%# create figure
a = 5
hFig = figure('Name','Step 3 of 4: Choose data for each image','Menubar','none', 'Resize','off', ...
'WindowStyle','modal', 'Position',[300 300 1150 600], 'CloseRequestFcn',#cmdClose_Callback);
set(gcf,'NumberTitle','off')
movegui(hFig, 'center');
options = cellfun(#(c) c(end:-1:1), options, 'Uniform',false);
num = length(options);
%# get saved settings
selected = getappdata(hParentFig, 'opts');
a = 6
%# top/bottom panels
hPanBot = uipanel('Parent',hFig, 'BorderType','none', ...
'Units','normalized', 'Position',[0 0.0 1 0.2]);
hPanTop = uipanel('Parent',hFig, 'BorderType','none', ...
'Units','normalized', 'Position',[0 0.2 1 0.2]);
%# buttongroups in top panel
hBtnGrp = zeros(1,num);
width = 1/num;
for i=1:num
%# create button group
hBtnGrp(i) = uibuttongroup('Parent',hPanTop, ...
'Units','normalized', 'Position',[(i-1)*width 0 width 1]);
%# populate it with radio buttons
height = 1./numel(options{i});
for j=1:numel(options{i})
h = uicontrol('Parent',hBtnGrp(i), 'Style','Radio', ...
'Units','normalized', 'Position',[0.05 (j-1)*height 0.9 height], ...
'String',options{i}{j});
%# set initially selected values
if strcmp(selected{i},options{i}{j})
set(hBtnGrp(i), 'SelectedObject',h)
end
end
end
if k ~= num_files
%# save button in bottom panel
uicontrol('Parent',hPanBot, 'Style','pushbutton', ...
'Units','normalized', 'Position',[0.3 0.2 0.4 0.2], ...
'String','next', 'Callback',#callback);
else
uicontrol('Parent',hPanBot, 'Style','pushbutton', ...
'Units','normalized', 'Position',[0.3 0.2 0.4 0.2], ...
'String','start', 'Callback',#callback);
end
%# save button callback function
function callback(o,e)
a = 7
%# get selected values
hObjs = get(hBtnGrp(:), 'SelectedObject');
vals = get(cell2mat(hObjs),{'String'});
%# update settings
setappdata(hParentFig, 'opts',vals);
close(hFig)
a = 8
end
function cmdClose_Callback(hObject,varargin)
disp(['Close Request coming from: ',get(hObject,'Type')]);
a = 9
%do cleanup here
delete(hFig);
a = 10
end
end
if 'files' has two images, I push the 'next' button for the first figure, and in the second figure I close, I get:
a = 1
a = 2
a = 5
a = 6
a = 3
a = 7
Close Request coming from: figure
a = 9
a = 10
a = 8
a = 4
a = 5
a = 6
a = 3
Close Request coming from: figure
a = 9
a = 10
a = 4
above the line: hOptsGUI = secondaryGUI(hFig, options, k, length(files));
I tried to put some lines. In order to testthe lines, I print a fit message:
if (ishandle(hFig))
disp('exists');
else disp('was closed');
end;
but it doesn't work :/
for each GUI that the user will close, the next callback will called:
function callback(o,e)
%# get selected values
hObjs = get(hBtnGrp(:), 'SelectedObject');
vals = get(cell2mat(hObjs),{'String'});
%# update settings
setappdata(hParentFig, 'opts',vals);
%# close options dialog
close(hFig)
end
so I just need to know in the next 'for loop' if this callback was called:
for k=1: length(files)
how can I do that?
Just check to see if hFig1 is a valid handle before you create the second figure.
if ishandle(hFig1)
hFig2 = figure(...)
else
return; % do something else
end
Repeat as needed.
function data = mainGUI(options, files)
% ...
% create main figure, with plot and options button
hFig = figure('Name','window 1','Visible','Off');
complete = callback;
if complete == 1
data = data;
else
data = 0;
end
% options button callback function
function complete = callback(o,e)
%save current options (sharing data between the two GUIs)
setappdata(hFig, 'opts',opts);
% display options dialog and wait for it
complete = 0;
for k = 1 : length(files)
hOptsGUI = secondaryGUI(hFig, options, k, length(files));
% ...
end
% we reached the end of the loop!
complete = 1;
end
I succeeded!
I used setappdata and getappdata in order to know if the second callback was called.
#Derek, Derek, thank you very much for your help and that you spent a lot of time for me!
function data = mainGUI(options, files)
%# current options
j = 1;
ops = cellfun(#(c) c(1), options, 'Uniform',false);
data{j} = [ops{1:length(ops)}];
j = j + 1;
options = cellfun(#(c) c(2:1:end), options, 'Uniform',false);
clear ops;
ops = cellfun(#(c) c(1), options, 'Uniform',false);
opts = [ops{1:length(ops)}];
%# create main figure, with plot and options button
hFig = figure('Name','window 1','Visible','Off');
callback
%# options button callback function
function callback(o,e)
%# save current options (sharing data between the two GUIs)
setappdata(hFig, 'opts',opts);
%# display options dialog and wait for it
for k=1: length(files)
hOptsGUI = secondaryGUI(hFig, options, k, length(files));
img = imread(files{k}); %# Read the data from your image file
hAxes = axes('Parent',hOptsGUI,'Units','pixels','Position',[362 242 424 359]); %# so the position is easy to define
image(img,'Parent',hAxes); %# Plot the image
set(hAxes,'Visible','off'); %# Turn the axes visibility off
out = 'FALSE';
setappdata(hFig,'some_var',out);
% show the images
%%Im = imread(files{k});
%%AxesH = axes('Units', 'pixels', 'position', [0.5, 10, 400, 260], 'Visible', 'off');
%%image('Parent', AxesH, 'CData', Im); %# add other property-value pairs as needed
waitfor(hOptsGUI);
some_other_var = getappdata(hFig,'some_var');
if (strcmp(some_other_var, 'OK') == 1)
%# get new options, and update plot accordingly
opts = getappdata(hFig, 'opts');
data{j} = opts;
j = j + 1;
else
k = length(files);
data = 0;
return;
end;
end
end
end
function hFig = secondaryGUI(hParentFig, options, k, num_files)
%# create figure
hFig = figure('Name','Step 3 of 4: Choose data for each image','Menubar','none', 'Resize','off', ...
'WindowStyle','modal', 'Position',[300 300 1150 600]);
set(gcf,'NumberTitle','off')
movegui(hFig, 'center');
options = cellfun(#(c) c(end:-1:1), options, 'Uniform',false);
num = length(options);
%# get saved settings
selected = getappdata(hParentFig, 'opts');
%# top/bottom panels
hPanBot = uipanel('Parent',hFig, 'BorderType','none', ...
'Units','normalized', 'Position',[0 0.0 1 0.2]);
hPanTop = uipanel('Parent',hFig, 'BorderType','none', ...
'Units','normalized', 'Position',[0 0.2 1 0.2]);
%# buttongroups in top panel
hBtnGrp = zeros(1,num);
width = 1/num;
for i=1:num
%# create button group
hBtnGrp(i) = uibuttongroup('Parent',hPanTop, ...
'Units','normalized', 'Position',[(i-1)*width 0 width 1]);
%# populate it with radio buttons
height = 1./numel(options{i});
for j=1:numel(options{i})
h = uicontrol('Parent',hBtnGrp(i), 'Style','Radio', ...
'Units','normalized', 'Position',[0.05 (j-1)*height 0.9 height], ...
'String',options{i}{j});
%# set initially selected values
if strcmp(selected{i},options{i}{j})
set(hBtnGrp(i), 'SelectedObject',h)
end
end
end
if k ~= num_files
%# save button in bottom panel
uicontrol('Parent',hPanBot, 'Style','pushbutton', ...
'Units','normalized', 'Position',[0.3 0.2 0.4 0.2], ...
'String','next', 'Callback',#callback);
else
uicontrol('Parent',hPanBot, 'Style','pushbutton', ...
'Units','normalized', 'Position',[0.3 0.2 0.4 0.2], ...
'String','start', 'Callback',#callback);
end
%# save button callback function
function callback(o,e)
out = 'OK';
setappdata(hParentFig,'some_var',out);
%# get selected values
hObjs = get(hBtnGrp(:), 'SelectedObject');
vals = get(cell2mat(hObjs),{'String'});
%# update settings
setappdata(hParentFig, 'opts',vals);
%# close options dialog
close(hFig)
end
function cmdClose_Callback(hObject,varargin)
%do cleanup here
delete(hFig);
end
end
There is no call to close the figure from the first GUI.
You may want to add a call close(hFig) to the end of the mainGUI function.
Related
I have a quite complex function that I plot using fsurf with a reasonably high MeshDensity (I cannot go much lower than the default, which is 35). Exporting this figure (saveas(gcf, 'file.pdf', 'pdf');) results in a 20-something MB pdf file of very nice quality, which nonetheless renders terribly slow. I would like to reduce the file size and, most importantly, the complexity of this pdf file, without exporting the whole plot (by which I mean the whole MATLAB figure) as a bitmap. How can I do that?
The perfect answer would explain how I can convert the surface plot (by which I mean, just the colored function surface on the white background) into a bitmap while maintaining the vectorized nature of axes and labels.
Update: Here's an example of such a plot.
This is my function BitmapRender, which Bitmap-renders part of the figure:
%% Test Code
clc;clf;
Objects = surf(-4-2*peaks);
hold('on');
Objects(2 : 50) = plot(peaks);
Objects(51) = imagesc([20 40], [0, 5], magic(100));
hold('off');
ylim([0 10]);
zlim([-10 15]);
Objects(1).Parent.GridLineStyle = 'none';
view(45, 45);
set(gcf, 'Color', 'white');
rotate3d on
saveas(gcf, 'pre.pdf');
BitmapRender(gca, Objects(2 : 3 : end));
% BitmapRender(gca, Objects(2 : 3 : end), [0.25 0.25 0.5 0.5], false);
saveas(gcf, 'post.pdf');
The function itself is pretty simple, except for the (re-)handling of visibility, as pressing the space key (after rotating, zooming etc) re-renders the figure.
function BitmapRender(Axes, KeepObjects, RelativePosition, Draft, Key)
if nargin < 2
KeepObjects = [];
end
if nargin < 3
RelativePosition = [0 0 1 1];
end
if nargin < 4
Draft = false;
end
if nargin < 5
Key = '';
end
Figure = Axes.Parent;
FigureInnerWH = Figure.InnerPosition([3 4 3 4]);
PixelPosition = round(RelativePosition .* FigureInnerWH);
if isempty(Key)
OverlayAxes = axes(Figure, 'Units', 'Normalized', 'Position', PixelPosition ./ FigureInnerWH);
if Draft
OverlayAxes.Box = 'on';
OverlayAxes.Color = 'none';
OverlayAxes.XTick = [];
OverlayAxes.YTick = [];
OverlayAxes.HitTest = 'off';
else
uistack(OverlayAxes, 'bottom');
OverlayAxes.Visible = 'off';
end
setappdata(Figure, 'BitmapRenderOriginalVisibility', get(Axes.Children, 'Visible'));
Axes.CLimMode = 'manual';
Axes.XLimMode = 'manual';
Axes.YLimMode = 'manual';
Axes.ZLimMode = 'manual';
hManager = uigetmodemanager(Figure);
[hManager.WindowListenerHandles.Enabled] = deal(false);
set(Figure, 'KeyPressFcn', #(f, e) BitmapRender(gca, KeepObjects, RelativePosition, Draft, e.Key));
elseif strcmpi(Key, 'space')
OverlayAxes = findobj(Figure, 'Tag', 'BitmapRenderOverlayAxes');
delete(get(OverlayAxes, 'Children'));
OriginalVisibility = getappdata(Figure, 'BitmapRenderOriginalVisibility');
[Axes.Children.Visible] = deal(OriginalVisibility{:});
else
return;
end
if Draft
return;
end
Axes.Visible = 'off';
KeepObjectsVisibility = get(KeepObjects, 'Visible');
[KeepObjects.Visible] = deal('off');
drawnow;
Frame = getframe(Figure, PixelPosition);
[Axes.Children.Visible] = deal('off');
Axes.Visible = 'on';
Axes.Color = 'none';
if numel(KeepObjects) == 1
KeepObjects.Visible = KeepObjectsVisibility;
else
[KeepObjects.Visible] = deal(KeepObjectsVisibility{:});
end
Image = imagesc(OverlayAxes, Frame.cdata);
uistack(Image, 'bottom');
OverlayAxes.Tag = 'BitmapRenderOverlayAxes';
OverlayAxes.Visible = 'off';
end
Obviously, the solution is pixel-perfect in terms of screen pixels. Two pdf files (pre and post) look like this. Note that surface, image and some plot lines are bitmap rendered, but some other plot lines, as well as axes and labels are still vectorized.
I tried to write an animation code in Matlab that repeats itself in every two seconds. The core animation scheme is as below:
Please take care the gif is repeating the core animation, originally there is only one cycle.
Here is the code:
% Figure settings
h= figure(2);
set(h, 'Position', [100 50 1200 750])
set(h,'Toolbar','None','Menubar','None')
set(h,'Name','Animation')
set(gcf,'doublebuffer','off');
set(gca, 'xlimmode','manual','ylimmode','manual','zlimmode','manual',...
'climmode','manual','alimmode','manual');
xlim([-200 1350])
ylim([-250 800])
set(gca,'xtick',[],'ytick', [], 'Position', [0 0 1 1]);
%Parameters
diameter = 60; %spot çapı
RamanX = 350; %ölçüm noktssı x konumu
nOfSpots = 4; %spot sayısı
spotCount = 0; %toplam spot sayısı
initPos = [50 150;50 300; 50 450; 50 600]; %konum 1
posII = [350 150;350 300; 350 450; 350 600]; %konum 2
Choice = rand(1,4)<.5; %Ölçüm sonunda verilen karar
deltaY2 = 100; % spotlar arası mesafe
x11 = zeros(nOfSpots,2);
x22 = zeros(nOfSpots,2);
x22a = zeros(nOfSpots,2);
x22b = zeros(nOfSpots,2);
for i=1:nOfSpots
x11(i,:) = [RamanX 150*(i-1)];
x22(i,:) = [800 50+deltaY2*(i-1)];
end
for i=1:nOfSpots/2
x22a(2*i-1,:) = [1280 -270+250*(i-1)];
x22a(2*i,:) = [1075 -270+250*(i-1)];
x22b(2*i-1,:) = [1280 220+250*(i-1)];
x22b(2*i,:) = [1075 220+250*(i-1)];
end
%Add 4 Circles to initial position
for i=1:nOfSpots
% Drag & Drop elipsler yerleştiriliyor
spot(i) = imellipse(gca, [initPos(i,1),initPos(i,2),diameter,diameter]);
spotCount = spotCount+1;
%elips özellikleri
setFixedAspectRatioMode(spot(spotCount), 'TRUE');
setResizable(spot(spotCount),0);
posSpot(spotCount,:) = getPosition(spot(i));
end
%Move Circles to posII
r = sqrt(sum(bsxfun(#minus,posII(:,1),initPos(:,1)).^2,2));
v = 30;
stepsize = ceil(r/v);
xstep = (posII(:,1)-initPos(:,1))/stepsize;
for i=1:stepsize
for j=1:nOfSpots
setPosition(spot(j), [initPos(j,1)+xstep(j)*i, initPos(j,2), diameter, diameter] )
posSpot(spotCount,:) = getPosition(spot(j));
end
pause(0.15)
end
%Move Circles to posIII
velocity = 30;
r2a = sqrt(sum(bsxfun(#minus,x22a,x11).^2,2));
stepsize2a = max(ceil(r2a/velocity));
r2b = sqrt(sum(bsxfun(#minus,x22a,x11).^2,2));
stepsize2b = max(ceil(r2b/velocity));
% Eğer öllçüm seçimi 1 ise taşı
for i=1:nOfSpots
if(Choice(i))
xstep2(i) = (x22a(i,1)-x11(i,1))./stepsize2a;
ystep2(i) = (x22a(i,2)-x11(i,2))./stepsize2a;
else
xstep2(i) = (x22b(i,1)-x11(i,1))./stepsize2b;
ystep2(i) = (x22b(i,2)-x11(i,2))./stepsize2b;
end
end
stepsize2 = max([stepsize2a stepsize2b]);
% Eğer ölçüm seçimi 0 ise taşı
for i=1:stepsize2
for j=1:nOfSpots
if(Choice(j))
setPosition(spot(j), [posII(j,1)+xstep2(j)*i, posII(j,2)+ystep2(j)*i, diameter, diameter] )
posSpot(spotCount,:) = getPosition(spot(j));
end
end
pause(0.15)
end
for i=1:stepsize2
for j=1:nOfSpots
if(~Choice(j))
setPosition(spot(j), [posII(j,1)+xstep2(j)*i, posII(j,2)+ystep2(j)*i, diameter, diameter] )
posSpot(spotCount,:) = getPosition(spot(j));
end
end
pause(0.15)
end
if(spotCount > 0)
for i=1:4
delete(spot(i))
end
end
The code doing this is a script not a function, say "animation.m". Now I am trying repeat this code in every 2 seconds. I tried to use loops with tic - toc commands, but the loop does not go to other cycle before finishing "animation.m". I need to get it work in the background.
One of my friend suggested me to use trigger. But, honestly, I could not apply the trigger command for my code even when I functionalized it.
Any help?
Edit:
The graphical flow chart of the problem is below:
I created an example that shows how it could be done.
Modifying your code, to draw just "one animated step" was too much work.
I decided to used your code to create all frames from advance (for example purpose).
I guess you are going to realize, that implementing background animation in Matlab is more difficult than you thought (unless I missed some hidden Matlab feature).
Matlab has very limited threading support, so I used a periodic timer.
My code sample does the following:
Build animation - create a cell array of all animated images.
You should avoid it, because it takes to much time (and memory).
I used it instead of modifying your code to draw one animated image.
Setup a periodic timer object with 0.2 seconds period (0.2 as an example).
I added a loop that illustrates the foreground processing (calculating sin(x) as an example).
Notice: I added small pause in the "foreground processing" loop.
The timer invokes a callback function every 0.2 seconds.
In the callback function the next animated frame is shown.
The timer is used for simulating a background execution.
You should replace the imshow, with your "animation step" function, that draws the frame (instead of showing a frame created from advance).
Here is the code sample (with your modified code included):
function TimerAnimation()
%Build set of images for animation.
[h_figure, Frames] = BuildAnimation();
t = timer;
t.TimerFcn = #timerFcn_Callback; %Set timer callback function
t.ExecutionMode = 'fixedRate'; %Set mode to "singleShot" - execute TimerFcn only once.
t.StartDelay = 0.1; %Wait 0.1 second from start(t) to executing timerFcn_Callback.
t.Period = 0.2; %Set period to 0.2 seconds.
%Turn on figure visibility
set(h_figure, 'Visible', 'on');
frame_counter = 1;
start(t) %Start timer;
%Do some other job...
%The animation is executed in the background (kind of in the background).
for x = 1:20000
y = sin(x/10000); %Calculate somthing...
if (mod(x, 100) == 0)
disp(['sin(', num2str(x/10000), ') = ', num2str(y)]); %Display somthing...
end
if (~isvalid(h_figure))
%Break loop if user closed the animation figure.
break;
end
%Must insert pause to "tight loop", allowing animation to run.
pause(0.01);
end
stop(t) %Stop timer;
delete(t); %Delete timer object.
if (~isvalid(h_figure))
close(h_figure);
end
%Timer function is executed every period of 0.2 seconds.
function timerFcn_Callback(mTimer, ~)
%Increse animation frame counter.
%figure(h_figure); %Set fo h_figure to be active figure.
h_axes = get(h_figure, 'CurrentAxes'); %Get axes of h_figure
imshow(Frames{frame_counter}, 'Parent', h_axes); %Display frame number frame_counter.
drawnow; %Force refresh.
frame_counter = mod(frame_counter, length(Frames)) + 1; %Advance to next frame (cyclically).
end
end
function [h, Frames] = BuildAnimation()
%Build set of images for animation.
%h - return handle to figure
%Frames - return cell array of animation images.
counter = 1;
% Figure settings
%h = figure(2);
%Create invisible figure.
h = figure('Visible', 'off');
set(h, 'Position', [100 50 1200 750])
set(h,'Toolbar','None','Menubar','None')
set(h,'Name','Animation')
set(gcf,'doublebuffer','off');
set(gca, 'xlimmode','manual','ylimmode','manual','zlimmode','manual',...
'climmode','manual','alimmode','manual');
xlim([-200 1350])
ylim([-250 800])
set(gca,'xtick',[],'ytick', [], 'Position', [0 0 1 1]);
%Parameters
diameter = 60; %spot ?ap?
RamanX = 350; %?l??m noktss? x konumu
nOfSpots = 4; %spot say?s?
spotCount = 0; %toplam spot say?s?
initPos = [50 150;50 300; 50 450; 50 600]; %konum 1
posII = [350 150;350 300; 350 450; 350 600]; %konum 2
Choice = rand(1,4)<.5; %?l??m sonunda verilen karar
deltaY2 = 100; % spotlar aras? mesafe
x11 = zeros(nOfSpots,2);
x22 = zeros(nOfSpots,2);
x22a = zeros(nOfSpots,2);
x22b = zeros(nOfSpots,2);
for i=1:nOfSpots
x11(i,:) = [RamanX 150*(i-1)];
x22(i,:) = [800 50+deltaY2*(i-1)];
end
for i=1:nOfSpots/2
x22a(2*i-1,:) = [1280 -270+250*(i-1)];
x22a(2*i,:) = [1075 -270+250*(i-1)];
x22b(2*i-1,:) = [1280 220+250*(i-1)];
x22b(2*i,:) = [1075 220+250*(i-1)];
end
%Add 4 Circles to initial position
for i=1:nOfSpots
% Drag & Drop elipsler yerle?tiriliyor
spot(i) = imellipse(gca, [initPos(i,1),initPos(i,2),diameter,diameter]);
spotCount = spotCount+1;
%elips ?zellikleri
setFixedAspectRatioMode(spot(spotCount), 'TRUE');
setResizable(spot(spotCount),0);
posSpot(spotCount,:) = getPosition(spot(i));
end
%Move Circles to posII
r = sqrt(sum(bsxfun(#minus,posII(:,1),initPos(:,1)).^2,2));
v = 30;
stepsize = ceil(r/v);
xstep = (posII(:,1)-initPos(:,1))/stepsize;
for i=1:stepsize
for j=1:nOfSpots
setPosition(spot(j), [initPos(j,1)+xstep(j)*i, initPos(j,2), diameter, diameter] )
posSpot(spotCount,:) = getPosition(spot(j));
end
%pause(0.15)
%Get frame, convert frame to image, and store image in Frames
Frames{counter} = frame2im(getframe(h));counter = counter + 1;
end
%Move Circles to posIII
velocity = 30;
r2a = sqrt(sum(bsxfun(#minus,x22a,x11).^2,2));
stepsize2a = max(ceil(r2a/velocity));
r2b = sqrt(sum(bsxfun(#minus,x22a,x11).^2,2));
stepsize2b = max(ceil(r2b/velocity));
% E?er ?ll??m se?imi 1 ise ta??
for i=1:nOfSpots
if(Choice(i))
xstep2(i) = (x22a(i,1)-x11(i,1))./stepsize2a;
ystep2(i) = (x22a(i,2)-x11(i,2))./stepsize2a;
else
xstep2(i) = (x22b(i,1)-x11(i,1))./stepsize2b;
ystep2(i) = (x22b(i,2)-x11(i,2))./stepsize2b;
end
end
stepsize2 = max([stepsize2a stepsize2b]);
% E?er ?l??m se?imi 0 ise ta??
for i=1:stepsize2
for j=1:nOfSpots
if(Choice(j))
setPosition(spot(j), [posII(j,1)+xstep2(j)*i, posII(j,2)+ystep2(j)*i, diameter, diameter] )
posSpot(spotCount,:) = getPosition(spot(j));
end
end
% pause(0.15)
%Get frame, convert frame to image, and store image in Frames
Frames{counter} = frame2im(getframe(h));counter = counter + 1;
end
for i=1:stepsize2
for j=1:nOfSpots
if(~Choice(j))
setPosition(spot(j), [posII(j,1)+xstep2(j)*i, posII(j,2)+ystep2(j)*i, diameter, diameter] )
posSpot(spotCount,:) = getPosition(spot(j));
end
end
% pause(0.15)
%Get frame, convert frame to image, and store image in Frames
Frames{counter} = frame2im(getframe(h));counter = counter + 1;
end
if(spotCount > 0)
for i=1:4
delete(spot(i))
end
end
imshow(Frames{1})
end
Example for what I meant by "drawing just one animated step":
function TimerAnimation2()
%Initiazlie animation.
param = InitAnimation();
%Same code as in previous example.
t = timer;t.TimerFcn = #timerFcn_Callback;t.ExecutionMode = 'fixedRate';t.StartDelay = 0.1;t.Period = 0.2;start(t)
for x = 1:20000;if (~isvalid(param.h)), break;end;pause(0.01);end
stop(t);delete(t);if (isvalid(param.h)), close(param.h);end
%Timer function is executed every period of 0.2 seconds.
function timerFcn_Callback(mTimer, ~)
%Animation single step
param = StepAnimation(param);
end
end
function param = InitAnimation()
h = figure;
set(h, 'Position', [100 50 1200 750]);set(h,'Toolbar','None','Menubar','None');set(h,'Name','Animation');set(gcf,'doublebuffer','off');
set(gca, 'xlimmode','manual','ylimmode','manual','zlimmode','manual', 'climmode','manual','alimmode','manual');
xlim([-200 1350]);ylim([-250 800]);set(gca,'xtick',[],'ytick', [], 'Position', [0 0 1 1]);
%Initialize param struct (param struct keeps animation parameters).
param.h = h;
param.x = 10;
param.y = 10;
%Draw rectangle in position x, y
h_axes = get(param.h, 'CurrentAxes');
rectangle('Position', [param.x param.y 20 20], 'Parent', h_axes);
end
%Example fo single animation step
%Get exsiting animation param as input, and retuen updated param as output.
function param = StepAnimation(param)
h_axes = get(param.h, 'CurrentAxes');
%Update param (to be used in next StepAnimation).
param.x = param.x + 10;
param.y = param.y + 10;
if (param.x > 500), param.x = 10;end
if (param.y > 500), param.y = 10;end
%Draw rectangle in position x, y
rectangle('Position', [param.x param.y 20 20], 'Parent', h_axes)
drawnow; %Force refresh.
end
I am trying to add a timer a simulation i am working on. At the moment i can get the timer to display in the location i want, however i cant make the numbers clear each other, i.e they all just stack on top of each other slowly creating a solid black mess. I have tried implementing a clf function but it just clears the entire figure. The code for the timer is:
HH = 0; MM = 0; SS = 0;
timer = sprintf('%02d:%02d:%02d',HH,MM,SS);
text(-450,450,timer); %% adjust location of clock in graph using the first two arguments: (x,y) coordinates
for t = 1:86400
SS = SS + 1;
if SS == 60
MM = MM + 1;
SS = 0;
end
if MM == 60
HH = HH + 1;
MM = 0;
end
timer = sprintf('%02d:%02d:%02d',HH,MM,SS); %% construct time string after all adjustments to HH, MM, SS
clf(f,'reset'); %% clear previous clock display
text(-450,450,timer); %% re-plot time to figure
if t == EventTimes(1)
uav1 = uav1.uavSetDestin([event1(2:3) 0]);
plot(event1(2),event1(3),'+')
hold on
end
if t == EventTimes(2)
uav2 = uav2.uavSetDestin([event2(2:3) 0]);
plot(event2(2),event2(3),'r+')
hold on
end
Is there a way i can reset only the timer function so it displays properly?
You want to store the handle to the text object and update the String property of this existing object rather than creating a new text object every time.
%// The first time through your loop
htext = text(-450, 450, timer);
%// Every other time through the loop
set(htext, 'String', sprintf('%02d:%02d:%02d',HH,MM,SS)
You will also want to do something similar with the plot objects rather than clearing the figure and redrawing all of the plots every iteration.
Integrating this with your code we get something like:
%// Create the initial text object
HH = 0; MM = 0; SS = 0;
timerString = sprintf('%02d:%02d:%02d',HH,MM,SS);
htext = text(-450, 450, timeString);
%// Create the plot objects
hplot1 = plot(NaN, NaN, '+');
hplot2 = plot(NaN, NaN, 'r+');
for t = 1:86400
SS = SS + 1;
%// I could help myself and made this significantly shorter
MM = MM + (mod(SS, 60) == 0);
HH = HH + (mod(MM, 60) == 0);
%// Update the timer string
timerString = sprintf('%02d:%02d:%02d',HH,MM,SS);
set(htext, 'String', timerString);
%// Update your plots depending upon which EventTimes()
if t == EventTimes(1)
uav1 = uav1.uavSetDestin([event1(2:3) 0]);
set(hplot1, 'XData', event1(2), 'YData', event1(3));
elseif t == EventTimes(2)
uav2 = uav2.uavSetDestin([event2(2:3) 0]);
set(hplot2, 'XData', event2(2), 'YData', event2(3));
end
%// Force a redraw event
drawnow;
end
The code below works. You can copy-paste this code in case you don't understand what I ask below.
In my gui, I have a pushbutton, popupmenu and edittext. Pushbutton enables adding new strings to popupmenu with the answers obtained from inputdlg. The strings in popupmenu have additional information which is defined in windowType function. When scrolling between popupmenu list, pmh_call calls windowType function and displays the information on edittext. The information on windowType function is predefined. However, what I want is to add new window types and information to this function. This is the first time I develop a GUI. So, I may have started this saving new info business to a function all wrong. Any help is appreciated.
function [] = mygui(varargin)
S.fh = figure('Visible','on','numbertitle','off','Name','Gunebakan GUI',...
'units','pixels','Position',[500 500 200 100]);
S.pbh_definewindow = uicontrol(S.fh,'Style','pushbutton','String','Define window',...
'HorizontalAlignment','center','BackgroundColor',[0.6602 0.0234 0.2539],...
'Position',[10 80 100 20]);
S.pmh_window = uicontrol(S.fh,'Style','popupmenu','String',{'Type1','Type2'},...
'Value',1,'BackgroundColor','w','Position',[10 50 150 18]);
S.eth_windowlength = uicontrol(S.fh,'Style','edit','String','4','Position',[10 10 50 20]);
set(S.pbh_definewindow,'callback',{#pbh_call,S});
set(S.pmh_window,'callback',{#pmh_call,S});
function [] = pmh_call(varargin)
S = varargin{3};
string = get(S.pmh_window,{'String','Value'});
string = string{1}(string{2});
[ windowtypeinfo ] = windowType( string );
str = num2str(windowtypeinfo.length);
set(S.eth_windowlength,'String',str);
function [] = pbh_call(varargin)
S = varargin{3};
error = 1;
prompt = {'Type name:','Type length:'};
name = 'Yeni Agac Tanimlama';
numlines = 1;
defaultanswer = {'benimagacim','2'};
answer = inputdlg(prompt,name,numlines,defaultanswer);
options.Resize = 'on';
options.WindowStyle = 'normal';
options.Interpreter = 'tex';
q = get(S.pmh_window,'String');
error = 1;
while error == 1
if ~any(strcmpi(answer{1},q))
error = 0;
else
answer(1) = inputdlg('Type name already used, enter another!')
error = 1;
end
end
P = get(S.pmh_window,{'string','value'});
q(length(q)+1) = answer(1);
set(S.pmh_window,'string',q);
function [ windowtypeinfo ] = windowType( string )
if strcmpi(string,'Type1')
windowtypeinfo.typename = 'Type1';
windowtypeinfo.length = 4;
elseif strcmpi(string,'Type2')
windowtypeinfo.typename = 'Type2';
windowtypeinfo.length = 5;
end
The question isn't really well posed but I think I understand what you're asking. To answer your final thought, I would say there is a better way to store your data. Consider the following simplified example:
function testgui
% Initialize GUI
h.myfig = figure;
h.mybutton = uicontrol( ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.15 0.70, 0.70 0.15], ...
'String', 'Add Style' ...
);
h.mymenu = uicontrol( ...
'Style', 'popupmenu', ...
'Units', 'normalized', ...
'Position', [0.15 0.50 0.70 0.10], ...
'String', ' ' ...
);
h.myedit = uicontrol( ...
'Style', 'edit', ...
'Units', 'normalized', ...
'Position', [0.15 0.15 0.70 0.10], ...
'String', ' ' ...
);
set(h.mybutton, 'callback',{#addwindow, h});
set(h.mymenu, 'callback',{#changewindow, h});
% Initialize data structure
mydata(1).typename = 'Type1';
mydata(1).windowlength = 4;
mydata(2).typename = 'Type2';
mydata(2).windowlength = 5;
updatepopup(mydata, h);
% Set initial editbox value
set(h.myedit, 'String', mydata(1).windowlength);
% Store data for later
guidata(h.myfig, mydata);
end
function updatepopup(mydata, h) % Update strings in popup menu based on data array
typenames = {mydata.typename}; % Collect all the existing typenames
set(h.mymenu, 'String', typenames); % Update popup menu
end
function addwindow(~, ~, h) % Prompt user to add window
prompt = {'Type name:','Type length:'};
name = 'myprompt';
nlines = 1;
defaultanswer = {'asdf', '1'};
myanswer = inputdlg(prompt, name, nlines, defaultanswer);
% Prepare new information for storage
newwindow.typename = myanswer{1};
newwindow.windowlength = str2double(myanswer{2});
mydata = guidata(h.myfig); % Pull in existing data
mydata = [mydata newwindow]; % Add new data to existing data
updatepopup(mydata, h); % Update popup menu
guidata(h.myfig, mydata); % Store data for later
end
function changewindow(~, ~, h) % Update editbox based on popup menu selection
mydata = guidata(h.myfig); % Pull in stored data
windowselected = get(h.mymenu, 'Value'); % Get index of window selected
set(h.myedit, 'String', mydata(windowselected).windowlength); % Change editbox
end
Rather than manually getting your window type with a separate function (windowType() in your example), I would try storing your data in the GUI as a data structure and pulling it out as necessary. This allows you to use more generalized code and not have to think about how to handle every case with the loop you have now. Hopefully this is easy to follow and adapt to your needs.
You should use guide in order to easily develop GUI's in MATLAB. If you do, you will find that each element in your GUI is called by a handles.something.
For example:
Lets say that you want to add the string in the inputdlg to your popup menu, you should do something like this:
set(handles.popupMenu,'String',[predefStrings; get(handles.inputdlg,'String')]);
The 'String' argument in a popup menu must be an array of strings.
Unfortunately, I have two loops. that's why my code makes the first loop run and only when it is finished, it makes the second loop run.
But I want the gui to show the data simultaneously: in the hAxes and in the loading1.
How can I make it?
hFigure = figure('units','pixels','position',[300 300 424 470],'menubar','none',...
'name','start processing','numbertitle','off','resize','off');
hAxes = axes('Parent',hFigure,'Units','pixels','Position',[0 112 424 359]);
loading1 = uicontrol('style','text','unit','pix','position',[0 72 424 40],...
'backgroundcolor','r','fontsize',20);
%% shows the data on hAxes
for i = 5:100
if mod(i,2) == 0
set(hAxes,'Color','b');
else
set(hAxes,'Color','g');
end
drawnow;
end
%% shows the data on loading1
for i=1:200
image2 = horzcat('now processing ', 'image', num2str(i), '.jpg of 200 images');
set(loading1,'string',image2);
drawnow;
end
this code is of Peter:
function test1
hFigure = figure('units','pixels','position',[300 300 424 470],'menubar','none','name','start processing','numbertitle','off','resize','off');
% Your other setup calls
hAxes = axes('Parent',hFigure,'Units','pixels','Position',[0 112 424 359]);
loading1 = uicontrol('style','text','unit','pix','position',[0 72 424 40],'backgroundcolor','r','fontsize',20);
c = 1;
t = timer('TimerFcn', #color_change_fcn,'StartDelay',1.0);
start(t);
for i=1:200
image2 = horzcat('now processing ', 'image', num2str(i), '.jpg of 200 images');
set(loading1,'string',image2);
drawnow;
end
function color_change_fcn
if mod(c,2) == 0
set(hAxes,'Color','b');
else
set(hAxes,'Color','g');
end
drawnow;
c = c + 1;
end
end
It doesn't work (doesn't show the hAxes). I saw it doesn't make the color_change_fcn run (I tried to write: disp('test') in the first row of color_change_fcn function, but it prints nothing.
This seems to be related to your previous question, where you want the two loops to be running simultaneously (well at least appear to be that way).
Building on #Peter's answer, consider the following working example:
function timerDemo()
%# prepare GUI
hFig = figure('Menubar','none', 'Resize','off');
axes('XLim',[0 1], 'YLim',[0 1], 'Visible','off', ...
'Units','normalized', 'Position',[0.1 0.2 0.8 0.6])
hTxt = uicontrol('Style','text', 'FontSize',24, ...
'Units','normalized', 'Position',[0 0.9 1 0.1]);
hPatch = patch([0 0 1 1 0],[0 1 0 1 0],'k');
%# colors to cycle through
c = 1;
clr = lines(4);
%# create timer
delay = 0.5;
hTimer = timer('Period',delay, 'StartDelay',delay, ...
'ExecutionMode','FixedRate', 'TimerFcn',#timerCallback);
%# when figure is closed
set(hFig, 'CloseRequestFcn',#onClose);
%# process images
start(hTimer); %# start timer
for i=1:100
if ~ishandle(hFig), break; end
msg = sprintf('Processing image %d / %d', i, 100);
set(hTxt, 'String',msg)
%# some lengthy operation
pause(.1)
end
if isvalid(hTimer)
stop(hTimer) %# stop timer
delete(hTimer) %# delete timer
end
%# timer callback function
function timerCallback(src,evt)
if ~ishandle(hFig), return; end
%# incremenet counter circularly
c = rem(c,size(clr,1)) + 1;
%# update color of patch
set(hPatch, 'FaceColor',clr(c,:));
drawnow
end
%# on figure close
function onClose(src,evt)
%# stop and delete timer
if isvalid(hTimer)
stop(hTimer);
delete(hTimer);
end
%# call default close callback
feval(#closereq)
end
end
The code simulates running a lengthy processing step on a number of images, while at the same time showing an animation to keep the user entertained.
To keep the code simple, I am showing a patch that updates its color continuously (using a timer). This stands for the animated GIF image of "loading...".
Is this what you want? Just combine the loop bodies.
for i=1:200
if mod(i,2) == 0
set(hAxes,'Color','b');
else
set(hAxes,'Color','g');
end
image2 = horzcat('now processing ', 'image', num2str(i), '.jpg of 200 images');
set(loading1,'string',image2);
drawnow;
end
EDIT: OK, in that case, try a timer instead of the first loop
function output = main_function
% Your other setup calls
hAxes = axes('Parent',hFigure,'Units','pixels','Position',[0 112 424 359]);
c = 0;
t = timer('TimerFcn', #color_change_fcn, 'Period', 1.0);
start(t);
for i=1:200
image2 = horzcat('now processing ', 'image', num2str(i), '.jpg of 200 images');
set(loading1,'string',image2);
drawnow;
end
function color_change_fcn
if mod(c,2) == 0
set(hAxes,'Color','b');
else
set(hAxes,'Color','g');
end
drawnow;
c = c + 1;
end
end
Just remember that the MATLAB control flow is inherently single-threaded, so these callbacks won't run if MATLAB is busy working somewhere else.